第4章 缓存雪崩、穿透与击穿场景与应对
缓存故障是稳定性面试的高频阵地。本章聚焦三大经典问题——雪崩、穿透、击穿,梳理现象、原因与系统性解决思路。先通过一张回答框架图建立结构化表达习惯,再以三个问答卡片深度拆解实战细节。
三大故障解决方案速查表
| 故障类型 | 现象 | 根本原因 | 核心解决手段 |
|---|---|---|---|
| 缓存雪崩 | DB瞬时高并发 | 大量缓存同时过期 / 节点宕机 | 随机TTL、缓存预热、限流降级 |
| 缓存穿透 | 缓存永远无数据,DB被打穿 | 查询不存在的数据 | 布隆过滤器、缓存空值 |
| 缓存击穿 | 单个热点key失效瞬间DB压力激增 | 热点key过期 | 互斥锁、热点key永不过期 |
面试问答卡片
Q1: 如何解决缓存雪崩问题?
面试官考察点:是否理解雪崩的两种触发场景(同时过期 vs 节点宕机),能否给出体系化方案(预防+补偿+降级)。
回答框架:
- 定义雪崩:大量缓存同时失效导致流量直击数据库
- 分析原因:TTL集中 + 节点故障
- 解决方案:随机TTL、缓存预热、限流降级、多级缓存
- 总结:组合措施保障稳定性
示例回答:缓存雪崩因大量缓存同时过期导致数据库压力暴增。我在项目中为每个Key的TTL加上±随机偏移(如基础300秒±60秒);业务低峰期主动预热热点;并配置Sentinel限流,当DB QPS超阈值时返回缓存旧值或默认页,有效避免雪崩。
可能追问:随机TTL的范围如何确定?节点宕机场景如何单独应对?限流降级对用户影响如何评估?
避坑提醒:不要只依赖随机化,必须配合预热和限流;限流阈值需基于压测数据,避免误伤正常请求。
Q2: 如何解决缓存穿透问题?
面试官考察点:考察对穿透本质的认知(业务攻击 vs 数据缺失),能否讲清布隆过滤器的优缺点及空值缓存的处理方式。
回答框架:
- 定义穿透:查询不存在的数据,缓存失效
- 分析原因:恶意请求、数据库无此记录
- 解决方案:布隆过滤器、缓存空值(设置较短TTL)
- 总结:防止无效请求穿透
示例回答:缓存穿透指请求根本不存在的key绕过缓存打向DB。我采用布隆过滤器,在启动时加载所有可用ID,请求进来先判断bitmap,不存在直接拒绝;对于漏网之鱼,将空结果缓存30秒,后续相同请求直接返回空,大幅降低DB压力。
可能追问:布隆过滤器如何降低误判率?元素删除如何解决?空值缓存TTL设置依据是什么?
避坑提醒:布隆过滤器不支持删除,需定期重建;空值缓存TTL不宜过长,否则影响数据一致性。
Q3: 如何解决缓存击穿问题?
面试官考察点:是否理解热点key瞬时失效的并发问题,能否正确设计互斥锁或使用“永不过期+异步更新”模式。
回答框架:
- 定义击穿:单个热点key失效,大量请求同时查询DB
- 分析原因:热点key TTL到期且并发高
- 解决方案:互斥锁(SETNX)或热点key逻辑永不过期+后台更新
- 总结:保证只有一个请求重建缓存
示例回答:缓存击穿通常针对热搜商品。我采用互斥锁方案:当缓存未命中时,先尝试SETNX加锁,成功则查DB并回写缓存,失败则短暂自旋等待其他线程写入。为防死锁设置锁超时时间,同时热点key设置逻辑永不过期,由定时任务异步刷新。
可能追问:互斥锁如何保证公平性?自旋等待的合理时间?异步刷新如何保证数据一致性?
避坑提醒:互斥锁务必设置超时;自旋等待不能阻塞过多线程;热点key逻辑不过期方案需确保后台更新延迟低。