外观
一句话答案
穿透(查不存在的 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同时过期。