缓存雪崩是指大量缓存key同时过期或redis故障,导致请求瞬间穿透至数据库,引发数据库连接耗尽、响应超时甚至宕机;典型诱因包括统一ttl设置、主从切换失败等,应对需采用随机过期、逻辑过期、多级缓存及熔断降级等组合策略。

缓存雪崩:大批 key 同时过期或 Redis 故障
缓存雪崩不是个别 key 失效,而是成千上万个 key 在同一秒内集体过期,或者 Redis 实例宕机,导致所有读请求瞬间穿透到数据库。典型现象是:缓存命中率从 95% 直线跌到 5%,MySQL 连接池迅速耗尽,Too many connections 错误频发,服务响应超时甚至 500。
- 常见诱因包括:批量导入数据时统一设了
EXPIRE时间(比如都设为 3600 秒),整点任务触发后全部失效;Redis 主从切换失败、哨兵误判、云厂商底层故障等 - 单纯加机器扛不住——数据库连接数、CPU、IO 都会成为瓶颈,且容易引发级联超时
- 不能只靠“加 Redis 实例”,因为雪崩本质是流量模型突变,不是容量问题
随机过期时间 + 永久 key 分层策略
对非敏感业务数据(如商品详情、配置项),避免用固定 TTL,改用带抖动的过期时间。这不是“加个 random”,而是有依据的偏移:
- 基础 TTL 设为 3600 秒,再叠加 ±300 秒随机值:
expireAt(key, now + 3600 + ThreadLocalRandom.current().nextInt(-300, 301)) - 对真正热点数据(如首页 banner、活动开关),直接不设过期时间,改用「逻辑过期」:缓存 value 中嵌入
expireTime字段,读取时判断是否逻辑过期,过期则异步刷新,而非阻塞重查 - 注意:
setIfAbsent和getSet在逻辑过期场景下必须配合版本号或时间戳,否则旧线程可能覆盖新写入
多级缓存不是堆机器,而是分层拦截
本地缓存(Caffeine)+ Redis + DB 不是简单串联,关键在拦截位置和失效策略:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 本地缓存放在应用进程内,TTL 设为秒级(如 60 秒),它不解决一致性,只挡掉重复请求的“毛刺”;
maximumSize(10000)必须设上限,否则 OOM - Redis 层承担最终一致性,用
setex或set命令显式控制过期,禁用expire单独调用(易漏) - 两级缓存都为空时,才允许打到 DB;但此时必须走互斥锁(如
lock:product:1001),防止击穿放大成雪崩 - 特别注意:本地缓存更新不能主动推送,必须靠「被动失效 + 读时重建」,否则集群间状态不同步
熔断降级和兜底数据才是最后防线
当 Redis 响应延迟超过阈值(如 P99 > 500ms)或错误率突增(如 redis.clients.jedis.exceptions.JedisConnectionException 频发),必须立刻切断依赖:
- 用 Resilience4j 或 Sentinel 做熔断器,触发后直接返回缓存过的兜底数据(如 JSON 文件或硬编码 fallback),而不是抛异常
- 兜底数据要定期更新(如每天凌晨从 DB 导出一次),不能是静态死值;更新脚本需校验 checksum,避免脏数据上线
- 禁止在熔断状态下尝试“重试 Redis”,这会把短暂抖动拖成持续雪崩
真正难的是边界条件:比如 Redis 集群部分节点失联、网络分区时主从不一致、布隆过滤器误判率上升导致穿透量激增——这些不会出现在压测报告里,但会在大促零点真实发生。










