什么是缓存雪崩?该如何解决?
一、什么是缓存雪崩
缓存雪崩,是高并发系统中缓存失效引发的数据库压力灾难。
正常流程:用户请求先访问Redis缓存,缓存命中就直接返回数据,不会访问数据库,以此减轻数据库压力。 缓存雪崩场景:大量缓存key在同一时刻集体失效(或者Redis服务宕机),大量并发请求绕过缓存,直接打到后端数据库。数据库瞬间流量超出承载上限,连接被打满、查询阻塞,严重时数据库卡死,进而导致整个服务不可用。
简单理解:缓存大面积“失效”,防护墙瞬间消失,所有流量直冲数据库。
⚠️ 注意区分几个容易混淆的概念:
- 缓存雪崩:大批量缓存同时失效 / Redis宕机,大量请求打DB,范围大,危害最重
- 缓存击穿:某一个热点key失效,大量并发请求同时抢这个key,持续访问数据库(单个热点)
- 缓存穿透:查询的数据本身在缓存和数据库都不存在,请求每次都直达数据库(查不存在的数据)
二、缓存雪崩常见的两个成因
-
批量key同时物理过期 开发时给一批缓存设置了相同的TTL过期时间,比如活动商品缓存统一设置过期时间为1小时。时间一到,这批key一起被Redis删除,瞬间大量缓存为空。这也是业务里最常见的雪崩原因。
-
Redis服务整体宕机、集群不可用 Redis节点故障、断电、主从切换失败,整个缓存服务无法提供服务,所有请求全部落到数据库。
三、缓存雪崩的解决方案
下面按照优先推荐顺序讲解,同时说明各自的优缺点与适用场景。
方案1:过期时间增加随机偏移(最简单,优先使用)
核心思路:避免大量key过期时间相同,打散过期时间,让缓存错峰失效。
原本:set key value ex 3600(统一1小时过期)
改造:基础过期时间上叠加随机值,例如基础3600秒,随机增加 0~600秒
expireTime = 3600 + random(0,600)
✅ 优点:改动极小,代码一行就能实现,性能无损耗 ❌ 缺点:只是降低同时失效概率,不能彻底杜绝雪崩;极端流量下依然存在风险 👉 定位:基础兜底方案,一般和其他方案搭配使用
方案2:逻辑过期方案
核心思路:不给Redis的key设置TTL(物理永不过期,Redis不会自动删除key),过期时间放在缓存value内部,由业务代码判断是否过期。 缓存存储结构示例:
{
"data": "业务真实数据",
"expireTime": 1790000000
}
执行流程:
- 查询缓存,拿到包装对象
- 判断当前时间是否超过对象内的
expireTime - 未过期:直接返回数据
- 已经逻辑过期:尝试获取分布式锁,抢到锁则开启异步线程更新缓存;没抢到锁,直接返回旧缓存数据
✅ 优点:从根源避免key被批量删除,不会出现缓存大面积为空;用户不需要等待数据库查询,响应速度快 ❌ 缺点:存在短暂数据不一致(更新前返回旧数据);Redis会持续存储key,需要额外策略清理冷数据;实现复杂,需要分布式锁、异步更新 👉 适用:允许短时间读到旧数据的场景,比如商品介绍、首页推荐、分类列表等;不适合余额、订单、库存这类强一致性场景
方案3:搭建Redis高可用集群(解决Redis宕机类雪崩)
如果雪崩根源是Redis挂了,靠调整过期时间没用。 方案:使用Redis主从+哨兵、Redis Cluster集群,做好持久化RDB+AOF。当主节点故障,自动完成故障转移,从节点升级为主节点,保证缓存服务尽量可用。
✅ 优点:提升缓存层本身稳定性,应对Redis单点故障 ❌ 缺点:无法解决key批量过期的雪崩;集群运维成本高;极端情况集群整体故障依然会失效 👉 定位:基础设施层面的保障,线上生产环境标配
方案4:服务层增加限流、熔断、降级机制
就算缓存全部失效,也要保护数据库,防止数据库被打挂。
- 限流:限制访问数据库的QPS,超过阈值直接拒绝
- 熔断:短时间内数据库异常次数过多,直接熔断,不再访问数据库
- 降级:数据库访问失败时,直接返回兜底默认数据、静态页面提示
✅ 优点:最后一道防线,保护数据库不崩溃 ❌ 缺点:属于事后防护,用户体验受损 👉 定位:兜底保护,所有高并发系统都建议配置
方案5:缓存预热
系统上线、大促活动前,提前把热点数据加载进Redis,避免上线瞬间大量缓存为空,大量请求查库。 通过定时任务或者脚本,提前批量写入热点商品、配置数据。
四、生产环境推荐组合方案
没有银弹,一般组合使用:
基础:过期时间加随机偏移 + Redis集群高可用 热点数据:热点key使用逻辑过期异步更新 兜底:Sentinel或者自研限流熔断降级
五、总结
缓存雪崩本质是缓存层大面积失效,流量击穿到数据库。
- 随机过期时间:低成本打散过期时间,适合绝大多数普通缓存
- 逻辑过期:保留旧缓存,异步刷新,适合允许短暂不一致的热点数据
- Redis高可用:解决缓存服务宕机
- 限流熔断降级:最后防线,防止数据库宕机
一句话总结:能打散就打散,热点数据用逻辑过期兜底,Redis保证高可用,最后配上熔断限流守住数据库。