第4章 缓存雪崩、穿透与击穿场景与应对

缓存故障是稳定性面试的高频阵地。本章聚焦三大经典问题——雪崩、穿透、击穿,梳理现象、原因与系统性解决思路。先通过一张回答框架图建立结构化表达习惯,再以三个问答卡片深度拆解实战细节。

定义问题 分析原因 解决方案 总结验证 什么是雪崩/穿透 大量同时失效/未命中 随机TTL/布隆/互斥锁 保证系统稳定

三大故障解决方案速查表

故障类型 现象 根本原因 核心解决手段
缓存雪崩 DB瞬时高并发 大量缓存同时过期 / 节点宕机 随机TTL、缓存预热、限流降级
缓存穿透 缓存永远无数据,DB被打穿 查询不存在的数据 布隆过滤器、缓存空值
缓存击穿 单个热点key失效瞬间DB压力激增 热点key过期 互斥锁、热点key永不过期

面试问答卡片

Q1: 如何解决缓存雪崩问题?

面试官考察点:是否理解雪崩的两种触发场景(同时过期 vs 节点宕机),能否给出体系化方案(预防+补偿+降级)。

回答框架:

  1. 定义雪崩:大量缓存同时失效导致流量直击数据库
  2. 分析原因:TTL集中 + 节点故障
  3. 解决方案:随机TTL、缓存预热、限流降级、多级缓存
  4. 总结:组合措施保障稳定性

示例回答:缓存雪崩因大量缓存同时过期导致数据库压力暴增。我在项目中为每个Key的TTL加上±随机偏移(如基础300秒±60秒);业务低峰期主动预热热点;并配置Sentinel限流,当DB QPS超阈值时返回缓存旧值或默认页,有效避免雪崩。

可能追问:随机TTL的范围如何确定?节点宕机场景如何单独应对?限流降级对用户影响如何评估?

避坑提醒:不要只依赖随机化,必须配合预热和限流;限流阈值需基于压测数据,避免误伤正常请求。

Q2: 如何解决缓存穿透问题?

面试官考察点:考察对穿透本质的认知(业务攻击 vs 数据缺失),能否讲清布隆过滤器的优缺点及空值缓存的处理方式。

回答框架:

  1. 定义穿透:查询不存在的数据,缓存失效
  2. 分析原因:恶意请求、数据库无此记录
  3. 解决方案:布隆过滤器、缓存空值(设置较短TTL)
  4. 总结:防止无效请求穿透

示例回答:缓存穿透指请求根本不存在的key绕过缓存打向DB。我采用布隆过滤器,在启动时加载所有可用ID,请求进来先判断bitmap,不存在直接拒绝;对于漏网之鱼,将空结果缓存30秒,后续相同请求直接返回空,大幅降低DB压力。

可能追问:布隆过滤器如何降低误判率?元素删除如何解决?空值缓存TTL设置依据是什么?

避坑提醒:布隆过滤器不支持删除,需定期重建;空值缓存TTL不宜过长,否则影响数据一致性。

Q3: 如何解决缓存击穿问题?

面试官考察点:是否理解热点key瞬时失效的并发问题,能否正确设计互斥锁或使用“永不过期+异步更新”模式。

回答框架:

  1. 定义击穿:单个热点key失效,大量请求同时查询DB
  2. 分析原因:热点key TTL到期且并发高
  3. 解决方案:互斥锁(SETNX)或热点key逻辑永不过期+后台更新
  4. 总结:保证只有一个请求重建缓存

示例回答:缓存击穿通常针对热搜商品。我采用互斥锁方案:当缓存未命中时,先尝试SETNX加锁,成功则查DB并回写缓存,失败则短暂自旋等待其他线程写入。为防死锁设置锁超时时间,同时热点key设置逻辑永不过期,由定时任务异步刷新。

可能追问:互斥锁如何保证公平性?自旋等待的合理时间?异步刷新如何保证数据一致性?

避坑提醒:互斥锁务必设置超时;自旋等待不能阻塞过多线程;热点key逻辑不过期方案需确保后台更新延迟低。