前言
书接上回,这次从理论上复习缓存雪崩和缓存击穿。
一、缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。提到定义,就容易让人想起昨天更新策略中有一个超时剔除的方法。如果只是单单使用超时剔除,就很容易在高并发下出现缓存雪崩。
1.雪崩场景一:大量缓存 key 集中过期
解决这个场景问题的核心思路:打散缓存的过期时间,避免所有 key 在同一时间失效;同时增加缓存的 “兜底” 机制。
方案 1:过期时间添加随机值
给每个缓存 key 的过期时间增加一个随机偏移量(比如 0~300 秒),让原本集中过期的 key 分散到不同时间过期,避免 “集体失效”。
方案 2:缓存永不过期 + 主动更新
对于秒杀、首页数据等核心业务的缓存,设置为永不过期,避免过期导致的雪崩;同时通过后台定时任务主动更新缓存数据。
- 缓存层面:不设置过期时间,key 永久有效;
- 更新层面:后台线程每隔一段时间(比如 30 分钟)主动查询数据库,更新缓存值;
- 兜底层面:如果定时任务失败,前端请求时发现缓存数据过旧(比如超过 1 小时),触发被动更新(加锁避免并发更新)。
2.雪崩场景二:Redis 服务宕机
解决这个场景问题的核心思路:增加缓存的可用性和兜底能力,避免缓存挂了直接打垮数据库。
方案 1:Redis 集群部署
单节点 Redis 宕机是雪崩的重要诱因,生产环境必须部署 Redis 集群。
- 主从复制:主节点负责写,从节点负责读,主节点宕机后从节点可切换;
- 哨兵(Sentinel):监控主从节点,自动完成故障转移,无需人工干预;
- Redis Cluster:分片集群,多主多从,单个节点宕机仅影响部分数据,整体服务可用。
这里由于还未学到redis集群,只能简单了解下概念。等后面再把这个坑填上。
方案 2:本地缓存 + 分布式缓存
在应用层增加本地缓存(比如 Java 的 Caffeine),形成 “本地缓存 → Redis → 数据库” 的多级缓存体系。当然可以采用其他多级缓存体系。
- 请求先查本地缓存,本地有则直接返回;
- 本地没有再查 Redis,Redis 有则返回并更新本地缓存;
- 两者都没有才查数据库,避免 Redis 宕机后所有请求直达数据库。
方案 3:服务熔断 / 降级
当 Redis 宕机或数据库压力达到阈值时,通过熔断 / 降级保护数据库:
- 熔断:暂时关闭访问数据库的请求,返回预设的默认值(比如 “系统繁忙,请稍后再试”);
- 降级:优先返回核心数据,非核心数据直接返回空,减少数据库压力;
3.实际风险场景
缓存预热后的集中过期的(最常见,秒杀/大促高频)
-
常采用基础TTL+随机偏移作为基础解决操作,按业务类型设基础TTL;叠加随机偏移量;爆款key偏移量缩小至0~600秒(10分钟),避免过早失效。
-
热点key永不过期+主动失效。爆款/核心key(秒杀爆款、首页数据)不设TTL;活动结束/数据更新后,通过消息队列/定时任务主动删除/更新缓存;后台巡检异常数据,手动触发失效。
-
不同品类差异化基础TTL(比如:服装2h、数码3h、其他1h),进一步打散过期时间,适用于品类繁多的业务。
Redis/缓存集群宕机
-
Redis集群高可用部署。字节自研Redis分片、淘宝则在开源的基础上开发了Redis Cluster)、腾讯自研Tair集群。
-
多级缓存兜底(本地+分布式)。像上面三个大厂都才用自己的集群Redis搭配Java的Caffeine来建立多级缓存。
缓存失效/预热失败,穿透至数据库
-
全链路熔断降级。设置触发指标,包括Redis响应超时率、数据库、数据库QPS超阈值等;分级降级,核心业务(比如支付、直播)返回旧缓存,非核心返回默认值; 熔断组件,Sentinel/Hystrix(通用)、自研组件(淘宝)。
-
接入层+数据库双重限流。字节(网关限流)、腾讯(TDSQL限流)、淘宝(网关+DB限流)。这我看的一头雾水,只能简单罗列几个名词,供感兴趣者了解了。
总结
缓存雪崩从基本思路入手,结合一下大厂实战经验不难发现:
- 处理该问题时不要依赖单一方案,需使用“组合拳”;
- 本地缓存注意失效:本地缓存TTL必须短于分布式缓存,避免本地缓存数据过旧,且需提供手动失效接口;
- 避免预热踩坑:预热时不使用大量并发写入,采用PipeLine批量操作;不预热非核心数据,减少缓存集群压力。
一些更详尽的知识还有待深入学习。

1467

被折叠的 条评论
为什么被折叠?



