缓存击穿需差异化设置超时时间:热点数据永不过期并异步刷新;普通数据TTL加随机偏移;空值缓存设为主TTL的1/5~1/3;本地缓存TTL须短于Redis且带jitter,避免假命中。

缓存击穿场景下,超时时间不能统一设成固定值,否则大量 key 同时过期会引发雪崩式穿透——必须对不同数据类型做差异化设置。
热点数据:永不过期 + 异步刷新
访问频次极高、更新频率极低的数据(比如首页 Banner、活动规则),直接禁用 TTL:
-
SET或SETNX写入时不带EX/PX参数,让 key 永不自动过期 - 靠后台定时任务或消息触发异步更新,例如每 5 分钟调用一次
SET覆盖旧值 - 避免用
EXPIRE去“续命”,防止因任务失败导致 key 突然失效
普通业务数据:TTL 随机化 + 空值短周期
用户资料、商品信息这类有明确生命周期的数据,TTL 必须加抖动:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 基础 TTL 设为 300 秒(5 分钟)后,再叠加 ±60 秒随机偏移:
EXPIRE key 300 + random.nextInt(120) - 60 - 空值缓存(
SET cache:shop:123 "" EX 60)的过期时间应显著短于正常数据,建议取主 TTL 的 1/5~1/3(如主 TTL 是 300 秒,空值设 60 秒) - 不推荐用
SETEX直接写空值,容易误覆盖后续真实数据;应先SET再EXPIRE控制粒度
本地缓存兜底:TTL 必须比 Redis 短且带 jitter
加 Caffeine/Guava 做二级缓存时,它的 TTL 不是锦上添花,而是缓解击穿的关键缓冲层:
- 本地缓存 TTL 应明显短于 Redis 主缓存(例如 Redis 设 300 秒,本地设 1–2 秒)
- 必须启用随机 jitter,比如 Caffeine 的
expireAfterWrite(1, TimeUnit.SECONDS).refreshAfterWrite(500, TimeUnit.MILLISECONDS)配合 jitter 工具类 - 若本地缓存 TTL ≥ Redis TTL,会导致“假命中”——本地还没过期但 Redis 已更新,数据不一致风险陡增
真正难处理的不是锁怎么写,而是 TTL 怎么设——它决定了流量是否会被错开、空值是否卡在缓存里太久、本地缓存是否成了脏数据温床。所有随机化逻辑必须在写入缓存那一刻就确定,而不是读时计算。

















