缓存击穿、缓存穿透、缓存雪崩三者都是缓存 + 数据库架构下常见问题,根源都是大量请求落到数据库,但是触发场景、对象不一样。
1. 概念
缓存穿透
查询一个根本不存在的数据,缓存和数据库都查不到。
场景:请求 id=-1、恶意传非法参数,这条数据数据库里本来就没有。
现象:缓存不会命中,请求直接穿透打到数据库;如果大量恶意请求,数据库压力打满。
关键点:数据本身不存在。
缓存击穿
热点 key 过期瞬间,大量并发请求打数据库。
场景:某一个热点 key(比如秒杀商品),缓存刚好失效,海量并发同时过来,绕过缓存直接访问 DB。
现象:就某一个热点 key 失效导致数据库压力飙升。
关键点:数据是存在的,只是缓存刚好过期,并发打过来。
缓存雪崩
大量缓存 key 同时失效 / Redis 宕机,大量请求全部涌向数据库。
场景:大量 key 设置相同过期时间,同一时刻集体过期;或者 Redis 服务宕机不可用。
现象:大批量缓存失效,数据库瞬间承受巨大流量,容易压垮数据库。
关键点:大批量 key 失效,不是单个 key。

2. 三者对比表
简单记忆口诀:
穿透:查无此物;
击穿:热点过期;
雪崩:集体翻车。
3. 各自解决方案
🟡 缓存穿透 解决方案
缓存空值:数据库查不到时,往 Redis 写入空对象,设置较短过期时间,下次请求直接命中缓存,不再访问 DB。
布隆过滤器 (BloomFilter):把所有有效业务 id 预加载进布隆过滤器,请求先过过滤器;不存在直接返回,不访问缓存和 DB。适合海量数据场景。
参数合法性校验:接口层校验 id、参数,拦截负数、非法参数。
接口限流:恶意请求做限流熔断。
注意:缓存空值会占用少量 Redis 内存;布隆过滤器不支持删除。
🟠 缓存击穿 解决方案
互斥锁(分布式锁):缓存失效时,只放一个线程去查数据库回写缓存,其他线程等待重试。如 Redisson 分布式锁。
缺点:会带来部分等待,降低吞吐量。
热点 key 永不过期(逻辑过期):Redis 不设置 TTL 过期时间;在 value 内部记录逻辑过期时间。线程后台异步更新缓存,不依赖 Redis 过期淘汰。
优点:高并发不用锁;缺点:会读到旧数据。
提前主动刷新热点缓存:热点数据在过期前,后台任务提前刷新缓存,避免过期瞬间大量请求。
🔴 缓存雪崩 解决方案
分两类:大量 key 同时过期、Redis 宕机
场景 1:大量 key 同一时间过期
过期时间加随机偏移:TTL 基础时间 + 随机值,打散过期时间,避免集体失效。最常用。
构建多级缓存:本地 Caffeine 缓存 + Redis 分布式缓存;Redis 失效还有本地缓存兜底。
定时任务主动刷新热点批量缓存。
场景 2:Redis 宕机不可用
Redis 高可用集群:主从、哨兵、Redis Cluster 集群,避免单点故障。
服务限流 & 熔断降级:Redis 不可用时,限制数据库访问量,部分请求直接返回降级结果,保护数据库。
服务隔离:缓存服务和数据库资源隔离。
限流队列:流量削峰,避免瞬时打垮 DB。

4. 容易混淆点辨析
击穿 vs 雪崩:
击穿:单个 key 过期;雪崩:大批量 key 失效。
穿透 vs 击穿:
穿透:数据压根不存在;击穿:数据真实存在,只是缓存过期。
雪崩可以由击穿放大而来:如果系统大量热点 key 同时击穿,现象就变成雪崩。
5. 生产最佳实践总结
参数校验 + 布隆过滤器应对穿透;
热点 key 使用逻辑过期 / 分布式锁解决击穿;
TTL 随机、Redis 集群、限流降级、多级缓存防止雪崩;
生产一般组合使用,不是单一方案。
本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。
欢迎访问 小易撩挨踢