Skip to content

缓存穿透/击穿/雪崩

三大经典问题:现象、成因、解法。

Updated View as Markdown
For humans

缓存穿透/击穿/雪崩

面试必考三连:穿透、击穿、雪崩。名字像,机制完全不同,先记一句话定位,再展开。

问题 一句话 打的是谁
穿透 查一个不存在的数据,缓存和库都没有 数据库(每次请求都穿透到库)
击穿 一个热点 key 过期瞬间,大量请求同时打库 数据库(单点瞬间流量)
雪崩 大量 key 同时过期或 Redis 挂了,流量全打库 数据库(整体流量)

缓存穿透

现象:恶意或巧合的请求查不存在的 key(如负数 ID),缓存永远 miss,每次都打到数据库,可能拖垮库。

解法:

方案 做法 取舍
缓存空值 查不到也缓存,TTL 设短(几分钟) 简单,需防大量空 key 占内存
布隆过滤器 请求先过过滤器,不存在直接返回 内存省,有误判(存在可能漏过)
参数校验 非法参数直接拒绝 治标,防不住合法格式的无效 key

缓存击穿

现象:热点 key(如秒杀商品)在过期瞬间,大量并发请求同时 miss,一起打到数据库。

解法:

  • 互斥锁:第一个请求拿锁重建缓存,其他请求等待或返回旧值。锁粒度要细,避免串行化所有读
  • 逻辑过期:不设物理 TTL,value 里带过期时间戳;读到逻辑过期时异步重建,请求先返回旧数据。实现复杂但无锁等待

缓存雪崩

现象:大量 key 同一时刻过期(如统一 TTL),或 Redis 实例宕机,流量瞬间全部打到数据库。

解法:

  • TTL 打散:过期时间加随机值(基础值加 0 到 300 秒随机),避免整批过期
  • 多级缓存:本地缓存(如 Caffeine)挡第一层,Redis 第二层,数据库兜底
  • 高可用:哨兵/集群防单点宕机,宕机期间限流降级
  • 限流降级:数据库侧限流,返回降级数据(如旧缓存、默认值)

对比与优先级

  • 穿透和击穿、雪崩的防护可以叠加:布隆过滤器挡穿透,TTL 打散挡雪崩,互斥锁挡击穿
  • 面试话术顺序:先说现象和危害,再说方案,再说取舍(空值缓存的内存代价、布隆过滤器的误判率、锁的粒度)

面试追问

  1. 穿透和击穿的区别? 穿透是数据不存在每次打库;击穿是热点 key 过期瞬间打库。一个是“有没有”的问题,一个是“过期时机”的问题
  2. 布隆过滤器有误判吗? 有,只能保证“不存在的一定不在”,存在可能误判。误判率由位数组大小和哈希函数数控制
  3. 互斥锁怎么实现? SETNX 拿锁重建缓存,其他请求拿不到就等或返回旧值。注意锁要设过期时间防死锁
  4. 逻辑过期和互斥锁怎么选? 要求强一致用互斥锁(有短暂等待),允许短暂旧数据用逻辑过期(无等待)
  5. 雪崩的 TTL 打散怎么做? TTL = 基础时间 + 随机偏移,让过期时刻均匀分布
Navigation

Type to search…

↑↓ navigate↵ selectEsc close