缓存击穿

某个热点Key在缓存失效的瞬间,大量请求直接穿透缓存层

方案设计

可选:缓存预热,在系统启动或者低峰的时候加载热点数据,这个可以根据历史的数据来进行预判预热

进行逻辑过期,缓存数据过期时间设置长点比如一天,保证不会击穿,value存三部分:datasoftExpireAthardExpireAt

data 后可以先返回旧值,同时触发异步刷新。

softExpireAt 后可以先返回旧值,同时触发异步刷新。

hardExpireAt 后不再返回旧值,必须互斥重建或降级。

这里也可以就只存一个硬过期时间,根据业务评估。然后请求缓存数据逻辑如下:

  1. 命中且 now < softExpireAt:直接返回新鲜数据。

  2. 命中且 softExpireAt <= now < hardExpireAt:返回旧值,并触发异步刷新。

  3. 命中且 now >= hardExpireAt:尝试抢锁,抢到则回源更新;没抢到短暂重试缓存,失败走降级不能无限重试

  4. 未命中:走互斥重建,防止并发全部穿透(如果设置了一个长过期时间不会到这步)

为什么需要逻辑过期,如果不逻辑过期可能会出现以下问题:

  1. 过期瞬间会出现延迟尖刺

    • 第一个请求查 DB,其他请求要么等锁、要么重试,RT 会在那一刻明显抖动。

  2. 会有缓存空窗期

    • 从 key 过期到重建完成这段时间,缓存是空的。

    • 如果持锁线程慢/超时/挂了,这个空窗会变长。

  3. 可用性兜底弱

    • DB 一旦慢或故障,没有旧值可返回,只能等待或失败。

    • 高峰期容易放大成线程池堆积、超时级联。

  4. 锁竞争成本高

    • 热点 key 过期时,大量请求都去抢锁/轮询,Redis 和应用端都会有额外开销。

  5. 多热点同刻过期时仍有“微雪崩”风险,即使单 key 被锁保护,很多 key 同时过期仍会带来 DB 瞬时压力。

以上是非常大并发时的方案,如果中低并发直接使用互斥重建即可

缓存雪崩

大量key集中失效,请求打到DB导致DB压力激增或者崩溃

常见的原因:

  1. 定时任务等情况批量的刷缓存设置了相同的TTL

  2. Redis服务不可用,比如主从切换失败了,网络故障

  3. 冷启动没有预热,比如服务器刚启动此时没有缓存

方案设计

  1. 分散Key过期时间,设置随机的TTL

  2. 热点缓存过期时间长或者永不过期,异步刷新数据

  3. 多级缓存架构(本地缓存+redis)

  4. 熔断降级和限流,比如返回默认值和使用Alibaba Sentinel在网关和服务内进行限流

  5. 定期压测和故障演练

缓存穿透

频繁查询数据库中不存在的数据,绕过了缓存。核心问题是恶意或者无效请求对系统的持续攻击

方案设计

参数的合法性校验->鉴权、黑白名单、限流IP->空值缓存(随机TTL)->布隆过滤器

注意点:保证数据一致性,即缓存层、布隆过滤器、数据库层对某个值是否存在和是否需要更新应该是一致的,不能出现下层没有数据上层还认为有的情况。