4. 缓存穿透/击穿/雪崩实战应对
缓存三大问题是分布式缓存面试的必考点。面试官不仅考察你是否知道概念,更关注你在真实场景中如何快速定位问题类型、选型应对策略以及量化治理效果。本章梳理三种问题的对比框架、三组高频问答以及一个完整的缓存治理项目模板。
| 问题类型 | 发生场景 | 核心原因 | 首选策略 | 关键工具 |
|---|---|---|---|---|
| 缓存穿透 | 查询不存在数据 | 缓存 & DB 均无 | 预判拦截 | 布隆过滤器 + 空值缓存 |
| 缓存击穿 | 热点 key 失效 | 热点过期 + 高并发 | 并发控制 | 互斥锁 + 二级缓存 |
| 缓存雪崩 | 大面积 key 失效 | 过期集中 / 宕机 | 过期打散 | 均匀过期 + 限流降级 |
Q1:如何排查并应对缓存穿透?
回答框架:
- 定义场景 —— 查询一个缓存和 DB 中都不存在的数据
- 分析危害 —— 请求直接打到 DB,严重时引发 DB 连接池耗尽
- 解决方案 —— 布隆过滤器预判 key 是否存在 + 空值缓存(短 TTL)
- 效果验证 —— 比较拦截前后 DB 查询量、响应时间
简短示例回答:“缓存穿透是请求不存在数据导致 DB 压力激增。我在 XX 项目使用 Guava 布隆过滤器拦截非法 key,配合空值缓存 TTL 30s,将穿透率从 15% 降至 0.1%,DB 查询量下降 90%,接口 P99 稳定在 5ms。”
可能追问:布隆过滤器误判率如何计算与控制?如何扩容?空值缓存 TTL 设置原则?
避坑提醒:不要对空值设置过长 TTL(建议 ≤60s),避免缓存堆积;布隆过滤器启动时需预热已有 key。
Q2:缓存击穿的解决方案有哪些?如何选型?
回答框架:
- 定义问题 —— 热点 key 失效瞬间大量并发请求回源 DB
- 方案对比 —— 互斥锁(控制回源线程数) vs 二级缓存(本地缓存兜底)
- 推荐选型 —— 高一致性用互斥锁,高可用用本地缓存 + 锁降级
- 效果量化 —— 给出并发前后 DB 峰值对比
简短示例回答:“热点 key 失效时我使用 Redisson 分布式锁控制仅一个线程回源,其余等待或走 Caffeine 本地缓存。秒杀场景下 QPS 10 万,DB 峰值从 1.2 万降至 500,系统可用性保持在 99.99%。”
可能追问:分布式锁如何避免死锁?本地缓存与 DB 一致性如何保证?热点 key 如何动态发现?
避坑提醒:不要使用同步锁(synchronized)跨进程无效;锁超时时间应大于回源耗时,建议结合看门狗自动续期。
Q3:如何预防与恢复缓存雪崩?
回答框架:
- 定义原因 —— 大量缓存同一时间过期 / Redis 集群宕机
- 预防措施 —— 过期时间加随机偏移 ±30% 打散窗口
- 恢复手段 —— 本地缓存兜底 + 限流熔断 + 快速重启
- 架构演进 —— 多级缓存(Redis + 本地 + CDN)
简短示例回答:“我采用基础 TTL 加随机 ±30% 偏移打散过期窗口,结合 Caffeine 本地缓存兜底和 Sentinel 限流降级。上线后 DB 日常 QPS 从 8 万降至 1.2 万,大促期间核心接口零雪崩。”
可能追问:Redis 集群宕机时如何快速恢复?限流阈值如何设定?多级缓存数据一致性怎么解决?
避坑提醒:避免所有 key 设置相同过期时间;本地缓存必须设置上限(如 10 万条)防止内存溢出;限流要区分核心与非核心接口。
项目案例:电商平台缓存治理与性能优化
| 业务背景 | 大促期间缓存穿透 & 击穿频发,DB 负载峰值超 85%,接口响应时间恶化至 200ms+ |
|---|---|
| 规模指标 | 日均 PV 5 亿+,峰值 QPS 50 万+,Redis 集群节点 200+,缓存命中率 92% |
| 技术栈 | Redis Cluster 6.x、Guava Bloom Filter、Redisson、Sentinel、Caffeine |
| 核心难点 |
|
| 面试高频追问 |
|
| 可迁移回答话术 | 在 xx 业务 中,我主导设计了 xx 方案,核心思路是 xx,最终将 xx 指标 从 xx 优化到 xx。这套方案可复用于 xx 场景,关键考量是 xx。 |
亮点成果:缓存命中率从 92% 提升至 99.2%,DB 峰值负载下降 70%,大促期间核心接口可用性 99.997%。