P12 使用 Redis 出现缓存击穿、雪崩、穿透怎么解决
面试题:Redis 缓存的三大经典问题——击穿、雪崩、穿透是什么?怎么解决?
三个问题先分清
| 问题 | 定义 | 典型表现 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,缓存没有、DB 也没有,每次请求都打到 DB | 恶意攻击用不存在的 id 打爆 DB |
| 缓存击穿 | 缓存中某个热点 key 过期,瞬间大量请求同时打到 DB | 热点商品/热搜词过期的一瞬间 |
| 缓存雪崩 | 大量 key 同时过期(或 Redis 宕机),请求全部打到 DB | 整批缓存设置了相同过期时间 |
解决方案
缓存穿透
- 缓存空值:查不到的数据也写缓存(value 为 null/空标记),设置较短过期时间;
- 布隆过滤器:请求前先判断 key 是否可能存在,不存在直接拒绝;
- 参数校验:非法 id(负数、超长、格式错误)直接拦截;
- 限流/风控:异常频次 IP 限流。
缓存击穿
- 互斥锁:缓存失效时,只让一个线程去查 DB 回填,其他线程等待(Redis setnx 分布式锁 / JVM 锁):
text
查缓存 miss → 加锁(setnx)→ 再查一次缓存 → 仍 miss 才查 DB → 回填缓存 → 释放锁- 逻辑过期:value 里存过期时间,后台异步刷新,不删除 key;
- 热点数据永不过期 + 后台任务定时更新。
缓存雪崩
- 过期时间加随机值:如基础 TTL + 随机 0~300 秒,避免同时过期;
- 多级缓存:本地缓存(Caffeine)+ Redis,本地兜底;
- Redis 高可用:集群/主从 + 哨兵,避免单点宕机;
- 服务降级:缓存不可用时,对非核心接口降级返回,保护 DB;
- 限流 + 熔断:DB 压力过大时熔断,防止雪崩放大。
加分点
- 布隆过滤器有误判率,适合"不存在是常态"的场景(如黑名单、防穿透 id);
- 互斥锁要注意防死锁(加过期时间)和防缓存击穿后的重复查询;
- 雪崩不止 key 过期,Redis 宕机也会导致,所以要有降级预案。
一句话总结
穿透用"缓存空值/布隆过滤器",击穿用"互斥锁/逻辑过期",雪崩用"过期时间随机化 + 多级缓存 + 高可用 + 降级",三个问题本质都是保护数据库不被瞬时流量打垮。