Skip to content
极高进阶

一句话答案

穿透(查不存在的 key→布隆/空值缓存)、击穿(热 key 过期→互斥锁/永不过期)、雪崩(大量 key 同时过期→随机 TTL/多级缓存)。

核心要点

缓存穿透(Cache Penetration):

现象:查询一个不存在的 key,缓存中没有,每次都直接打到 DB
场景:恶意攻击(大量查询 id=-1 等不存在的数据)
危险:DB 被大量无效查询压垮

解决方案:
  1. 缓存空值:查询结果为空时,也在缓存中写入 null(短过期时间如 5min)
     缺点:可能缓存大量无效 key
  
  2. 布隆过滤器(推荐):
     在请求到达缓存前,先用布隆过滤器判断 key 是否可能存在
     不存在 → 直接返回,不查 DB 也不查缓存
     缺点:有误判率(误判为存在的占少数),需要维护数据同步

缓存击穿(Cache Breakdown / Hot Key):

现象:某个热点 key 突然过期,大量并发请求同时打到 DB
场景:秒杀商品详情、热门文章的缓存刚好过期

解决方案:
  1. 互斥锁(Mutex):
     缓存失效时,只让一个线程查 DB 并重建缓存
     其他线程等待(或先返回旧数据)
     缺点:等待期间性能下降
  
  2. 逻辑过期(Logical Expiration):
     key 永不真正过期,但在 value 中存储过期时间戳
     发现逻辑过期 → 异步线程重建缓存,同时返回旧数据(不阻塞)
     优点:不阻塞请求;缺点:短暂返回旧数据(最终一致)

缓存雪崩(Cache Avalanche):

现象:大量缓存 key 同时过期,或 Redis 实例宕机,流量全部打到 DB
场景:大量 key 设置了相同的过期时间

解决方案:
  1. 过期时间随机化:在基础过期时间上加随机偏移(如 TTL + random(0, 300s))
  2. Redis 集群高可用:部署主从+哨兵或 Redis Cluster,避免单点故障
  3. 限流 + 降级:DB 前加限流,DB 承载不住时返回降级数据
  4. 本地缓存(多级缓存):Redis 宕机时,本地缓存(Caffeine)提供兜底
追问与易错

追问方向:

  • 布隆过滤器有什么缺点?如何解决?(误判率/不支持删除→Counting Bloom Filter)
  • 互斥锁方案的缺点?(等待时间长/锁失效问题)
  • 你们项目中用了哪种方案?为什么?

易错点:

  • ❌ 混淆三者的区别——穿透是 key 不存在,击穿是热 key 过期,雪崩是大量 key 同时过期
  • ❌ "空值缓存就完美解决穿透了"——海量不存在的 key 会占用大量内存,需设 TTL

💡 记忆锚点

穿透 = 查无此人(布隆过滤器拦门口),击穿 = 唯一保安下班众人涌入(互斥锁排队),雪崩 = 所有保安同时下班(错开下班时间 = 随机TTL)。三者区别:不存在/热key过期/大量key同时过期。