缓存预热、穿透、击穿、雪崩:一次讲清四个经典问题
缓存预热、穿透、击穿、雪崩:一次讲清四个经典问题
最近复习 Redis 缓存,把四个最容易混淆的经典问题整理成文:缓存预热、缓存穿透、缓存击穿、缓存雪崩。其中穿透和击穿一字之差,却是完全不同的场景。
一、为什么要用缓存
在高并发场景下,数据库的 QPS 瓶颈一般在千级到万级,而 Redis 可以轻松扛住十万级以上。引入缓存,就是把"热数据"从磁盘挪到内存,用空间换时间。
但缓存不是银弹——四个"坑"随之而来。
二、缓存预热
是什么:系统上线或大促前,提前把热点数据写入缓存,避免流量进来后逐个回源数据库。
典型场景:秒杀活动。活动开始时间已知,开始前把商品库存、详情页数据预热到 Redis,活动开始瞬间流量直接打在缓存上。
怎么做: 1. 启动时预热:应用启动后加载热点数据到缓存 2. 定时预热:定时任务在活动前刷新缓存 3. 手动预热:运营活动前通过后台触发
三、缓存穿透
是什么:查询一个根本不存在的数据,缓存里没有(也没法缓存),请求直接打到数据库。恶意攻击者常利用这点,用不存在的 ID 疯狂刷接口,把数据库打垮。

解决方案: 1. 缓存空值:查不到数据也缓存一个 null,设置短过期时间(如 5 分钟),防止同一 key 反复穿透 2. 布隆过滤器:请求前先过布隆过滤器,判断 key 是否存在,不存在直接返回,拦截大部分无效请求(允许极小误差) 3. 参数校验:入口校验非法参数(如 ID 格式、范围),把明显无效的请求挡在外面
四、缓存击穿
是什么:某个热点 key 恰好过期的一瞬间,大量并发请求同时打到数据库重建缓存。比如秒杀商品、热搜榜——key 失效的瞬间就是灾难。
注意:击穿是"存在的热点数据缓存刚好没了",与穿透(数据本身不存在)完全不同。

解决方案: 1. 互斥锁:key 过期后只允许一个线程去查库重建缓存,其他线程等待(最常用,如 Redisson 分布式锁) 2. 逻辑过期:缓存里额外存一个过期时间字段,发现"逻辑过期"先返回旧值,后台异步刷新 3. 热点 key 永不过期:不设置过期时间,由后台定时任务主动更新
五、缓存雪崩
是什么:大量 key 在同一时间过期,导致大量请求同时回源数据库,数据库瞬间被打垮。与击穿的区别:击穿是单个 key,雪崩是一批 key。

解决方案:
1. 过期时间加随机值:expire = 基础时间 + random(0~300s),避免 key 集体失效
2. 集群部署:多节点分散流量,单点故障不拖垮整体
3. 服务降级/限流:数据库压力过大时,直接返回降级数据(如默认值),保护数据库
六、一图区分四个概念
| 问题 | 本质 | 关键场景 | 核心方案 |
|---|---|---|---|
| 预热 | 提前加载 | 大促/秒杀前 | 定时/启动预热 |
| 穿透 | 查不存在的数据 | 恶意刷不存在 ID | 空值缓存、布隆过滤器 |
| 击穿 | 单个热点 key 过期瞬间 | 秒杀商品失效 | 互斥锁、逻辑过期 |
| 雪崩 | 大量 key 同时过期 | 缓存集体失效 | 随机过期时间、集群、降级 |
七、总结
一句话记忆: - 穿透:查"不存在"的东西 → 空值缓存 / 布隆过滤器 - 击穿:存在的东西缓存刚好没了 → 互斥锁 / 逻辑过期 - 雪崩:一堆 key 同时没了 → 随机过期 / 集群 / 降级 - 预热:让上面三个问题还没发生就提前解决
缓存是性能利器,但用之前,先想清楚这四兄弟怎么防。