缓存击穿
某个热点Key在缓存失效的瞬间,大量请求直接穿透缓存层
方案设计
可选:缓存预热,在系统启动或者低峰的时候加载热点数据,这个可以根据历史的数据来进行预判预热
进行逻辑过期,缓存数据过期时间设置长点比如一天,保证不会击穿,value存三部分:data、softExpireAt、hardExpireAt
data 后可以先返回旧值,同时触发异步刷新。
softExpireAt 后可以先返回旧值,同时触发异步刷新。
hardExpireAt 后不再返回旧值,必须互斥重建或降级。
这里也可以就只存一个硬过期时间,根据业务评估。然后请求缓存数据逻辑如下:
命中且 now < softExpireAt:直接返回新鲜数据。
命中且 softExpireAt <= now < hardExpireAt:返回旧值,并触发异步刷新。
命中且 now >= hardExpireAt:尝试抢锁,抢到则回源更新;没抢到短暂重试缓存,失败走降级不能无限重试
未命中:走互斥重建,防止并发全部穿透(如果设置了一个长过期时间不会到这步)
为什么需要逻辑过期,如果不逻辑过期可能会出现以下问题:
过期瞬间会出现延迟尖刺
第一个请求查 DB,其他请求要么等锁、要么重试,RT 会在那一刻明显抖动。
会有缓存空窗期
从 key 过期到重建完成这段时间,缓存是空的。
如果持锁线程慢/超时/挂了,这个空窗会变长。
可用性兜底弱
DB 一旦慢或故障,没有旧值可返回,只能等待或失败。
高峰期容易放大成线程池堆积、超时级联。
锁竞争成本高
热点 key 过期时,大量请求都去抢锁/轮询,Redis 和应用端都会有额外开销。
多热点同刻过期时仍有“微雪崩”风险,即使单 key 被锁保护,很多 key 同时过期仍会带来 DB 瞬时压力。
以上是非常大并发时的方案,如果中低并发直接使用互斥重建即可
缓存雪崩
大量key集中失效,请求打到DB导致DB压力激增或者崩溃
常见的原因:
定时任务等情况批量的刷缓存设置了相同的TTL
Redis服务不可用,比如主从切换失败了,网络故障
冷启动没有预热,比如服务器刚启动此时没有缓存
方案设计
分散Key过期时间,设置随机的TTL
热点缓存过期时间长或者永不过期,异步刷新数据
多级缓存架构(本地缓存+redis)
熔断降级和限流,比如返回默认值和使用Alibaba Sentinel在网关和服务内进行限流
定期压测和故障演练
缓存穿透
频繁查询数据库中不存在的数据,绕过了缓存。核心问题是恶意或者无效请求对系统的持续攻击
方案设计
参数的合法性校验->鉴权、黑白名单、限流IP->空值缓存(随机TTL)->布隆过滤器
注意点:保证数据一致性,即缓存层、布隆过滤器、数据库层对某个值是否存在和是否需要更新应该是一致的,不能出现下层没有数据上层还认为有的情况。