跳到主要内容
约 5 分钟3 张卡

缓存穿透、击穿、雪崩与热点 Key

缓存穿透、击穿和雪崩会把流量集中到数据库。热点 key 与大 key 还会耗尽单个 Redis 节点资源。本文负责故障识别、回源保护和恢复。

1. 面试核心​

先记住这几条,再读正文
  • 缓存穿透。 穿透持续查询不存在的数据,负缓存和布隆过滤器能减少回源。卡 · 缓存穿透
  • 缓存击穿。 击穿由热点失效触发,singleflight 合并同 key 的并发加载。
  • 缓存雪崩。 雪崩涉及大量键或节点失效,TTL 抖动分散到期,回源限流保护数据库。
  • 热点 Key。 单个热点 key 固定路由到一个分片,本地缓存可分担读取。
  • 大 Key 删除。 Redis 4.0 起提供 UNLINK,将键摘除与值内存回收分开。卡 · 热点 key

2. 缓存穿透​

无效 ID、随机 key 和已删除对象都能产生穿透。缓存与数据库均无对应数据,请求却持续回源。

  • 入口先检查参数格式、租户与访问权限。
  • 对确认不存在的对象缓存短期空值。
  • 布隆过滤器拦截确定不在集合中的 ID。
  • 对异常来源限流,按结果类型监控回源量。

负缓存需区分“不存在”和“数据库查询失败”。查询失败若被当成空值缓存,会遮住真实数据。新增对象后也要清除相应负缓存。

3. 布隆过滤器维护​

布隆过滤器用多个哈希位置表示集合成员。多个成员可共享位,因此存在误判。已有成员对应的位完整保留时,查询不会漏判它。

新增数据库记录尚未加入过滤器时,过滤器会拒绝该 ID。上线时可先构建新过滤器,再补齐增量并切换。重建期间需有回源或双读策略,避免丢掉新记录。

普通布隆过滤器不支持直接清位删除。共享位被清除后,其他成员会出现漏判。需要删除能力时,可选择计数或其他支持删除的结构。

Redis 6、7 的 BF 命令来自 RedisBloom 模块。部署时需确认模块可用,不能假定核心实例自带。

4. 缓存击穿​

单个热点 key 失效后,并发请求会同时加载同一数据。相同的昂贵查询因此集中到数据库。

singleflight 合并同 key 的加载,由一个请求回源。其他请求等待共享结果,并设置队列上限和等待超时。进程内 singleflight 只合并本实例请求。多实例负载还需全局回源限额或跨实例协调。

逻辑过期把业务到期时间存入值中。过期后允许返回旧值,同时启动后台刷新。它适合允许旧数据的接口。冷启动没有旧值时,仍需合并加载和失败处理。

互斥重建的租约边界见分布式锁。

5. 缓存雪崩​

同批键集中到期,或缓存整体不可用,都会造成雪崩。数据库要承接原本由缓存处理的请求。

  • 基础 TTL 加随机抖动,分散到期时间。
  • 分批预热,限制每批回源量。
  • 对数据库回源设置并发和队列上限。
  • 非关键接口返回可接受的旧值或明确降级结果。
  • 缓存与数据库分别进行容量测试。

TTL 抖动只分散到期时间。节点故障仍需高可用与回源保护共同处理。

6. 热点 key​

单个 key 路由到同一 Redis 分片。即使命中率为 100%,也会受到节点 CPU 和带宽限制。

按业务键采样请求量,再结合分片 CPU 和网络判断热点。读热点可使用本地缓存。复制多个读副本 key 时,需确认它们分布在不同槽和节点。

共享同一 hash tag 的 key 会落到同一个槽。仅修改 tag 外的后缀,无法分散该热点。副本更新还需处理失效和版本一致性。

可合并的写入可使用分片计数。要求全局严格顺序的操作,则需要统一协调。

7. 大 key​

大 key 放大内存、传输、删除和迁移成本。集合元素多时,全量读取也会长时间占用执行线程。

控制值大小和集合元素数量。遍历使用 SCAN 家族,并限制返回规模。它的游标边界见 SCAN 游标遍历。

Redis 4.0 起可用 UNLINK key 删除大 key。主线程先将键从键空间摘除,内存释放交给后台处理。释放简单对象时,实现也可直接完成。后台回收仍占 CPU 和内存带宽,应限制批量删除速度。

8. 防护链路​

回源保护应有完整的资源上限。

  1. 校验参数和权限,拦截无效 key。
  2. 限制来源和业务键的请求速率。
  3. 用本地或 Redis 缓存承接命中。
  4. 合并同 key 的加载,限制等待人数。
  5. 用回源并发、连接池和查询超时控制数据库压力。
  6. 失败时返回约定的旧值、缺省结果或错误。

每层的等待时间都应服从接口总预算。恢复阶段也需控制预热和重试速度。

9. 故障演练​

分别演练热点过期、大批过期和 Redis 不可用。数据库变慢与客户端连接池耗尽也应覆盖。

观察回源 QPS、加载等待和各分片 CPU、网络。再对照数据库连接等待和接口尾延迟。恢复阶段限制预热速度,防止重建流量再次压满数据库。

10. 常见问题​

10.1 永久 key 与重建​

永不过期可以消除该键的 TTL 到期。内存淘汰、故障和删除仍可让键消失。高频数据还需更新,因此仍要设计重建保护。

10.2 布隆过滤器的查询边界​

11 · 面试题卡片​

本页题目与参考回答

11.1 缓存穿透、击穿和雪崩分别如何处理​

出现公司:字节跳动

考察重点

  • 三类问题的流量来源和影响范围。
  • 负缓存、Bloom filter、合并加载和 TTL 抖动。
  • 回源限流、降级与故障恢复。

相关内容:缓存穿透至故障演练。

参考回答

穿透用参数校验、负缓存和布隆过滤器减少无效回源。

击穿用 singleflight 或互斥重建合并热点加载。雪崩用 TTL 抖动分散到期,并限制总回源量。

Redis 整体故障时,还需降级和数据库容量保护。热点 key 与大 key 要按分片 CPU、网络和命令延迟诊断。恢复过程同样要限制预热速度。

11.2 布隆过滤器为何会误判,新增和删除数据时要注意什么?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:共享位、数据同步和重建。

相关内容:布隆过滤器维护。

参考回答

不同成员共享位,会让不存在的值也通过检查。

已加入的成员在位完整时不会被漏判。数据库新增但过滤器尚未同步时,会出现业务漏查。普通布隆过滤器直接清位会影响其他成员,删除需另选结构。

出现公司:暂无已核验的公开来源(本站自测)

考察重点:访问频率、对象体积与异步释放。

相关内容:热点 key、大 key。

参考回答

热点 key 按访问频率判断,大 key 按大小和元素数判断。

两者可以同时存在。UNLINK 先摘除键,再异步处理较重的内存释放。它减少主线程释放大对象的停顿,后台成本仍然存在。

12. 参考资料​