4. 缓存击穿原理:热点Key失效瞬间的并发冲击

4.1 缓存击穿的定义

缓存击穿(Cache Breakdown / Hotspot Invalid)是指某个被持续高并发访问的热点 Key,在其缓存过期的瞬间,大量请求同时穿透到后端数据库,导致数据库负载瞬间飙升甚至崩溃的现象。

与缓存穿透不同,击穿针对的是确实存在的数据,只是因为缓存恰好失效,引发了并发回源的“惊群效应”。

核心特征:单点热点 + 瞬间失效 + 并发回源 = 数据库压力尖峰。

4.2 热点Key失效瞬间的并发冲击

假设一个热点商品 Key product:1001 的 TTL 设置为 60 秒。在失效瞬间,如果同时有 10,000 个请求到达,且所有请求都发现缓存 Miss,它们会同时执行回源查询数据库的逻辑:

  1. 缓存 Miss 阶段:所有请求同时查询 Redis,Key 已过期,返回空。
  2. 并发回源阶段:10,000 个请求同时向数据库发起 SELECT * FROM product WHERE id=1001。
  3. 数据库过载阶段:数据库连接池瞬间被打满,CPU 飙升,慢查询堆积。
  4. 雪崩传导阶段:数据库响应变慢,导致应用线程阻塞,最终可能引发整个服务链路超时熔断。
关键指标:击穿瞬间的 QPS 峰值 = 热点 Key 的并发访问量 × 回源耗时。若回源耗时 50ms,并发 10,000,则数据库需承受 200,000 QPS 的瞬时冲击。

4.3 击穿与穿透的本质区别

对比维度 缓存击穿 缓存穿透
数据是否存在 数据真实存在(如热点商品) 数据根本不存在(如恶意 ID)
失效原因 缓存 Key 过期 / 主动淘汰 缓存未命中 + 数据库无记录
并发特征 高并发集中在一个 Key 大量不同 Key 或随机 Key
数据库压力 瞬间尖峰,持续短 持续低效查询,可能长期存在
典型场景 秒杀商品、热搜榜单 恶意攻击、空数据查询
治理重点 互斥锁、预热、永不过期 布隆过滤器、空值缓存

4.4 击穿冲击的量化模型

设热点 Key 的并发请求数为 N,缓存失效后单次回源耗时为 T(单位:ms),则数据库承受的瞬时并发回源数 P 为:

P = N × (1 - cacheHitRate)
当 cacheHitRate = 0(失效瞬间)时,P = N

实际生产环境中,N 可能达到数万甚至数十万。以某电商大促为例:

  • 热点商品 Key 并发:50,000 QPS
  • 缓存 TTL:60 秒
  • 失效瞬间回源数:50,000(无保护措施)
  • 数据库连接池上限:200
  • 结果:数据库连接池溢出,服务不可用
治理启示:击穿治理的核心是将 P 从 N 降低到 1(只让一个请求回源),或通过预热将 cacheHitRate 维持在接近 100%。

4.5 击穿与穿透的决策树对比

缓存击穿 vs 缓存穿透 决策对比 缓存未命中 数据存在(击穿) 数据不存在(穿透) 热点 Key 失效瞬间 并发回源:N 个请求同时查 DB 数据库瞬间过载 恶意/无效 Key 持续请求 每次 Miss 都查 DB,无缓存 数据库持续低效负载 治理:互斥锁 + 预热 + 永不过期 治理:布隆过滤器 + 空值缓存 核心区别:击穿是“有数据但缓存没了”,穿透是“数据本身就不存在”

4.6 击穿治理的三大原则

  1. 互斥回源:同一时刻只允许一个线程回源查询数据库,其他线程等待或返回旧缓存。
  2. 热点预热:在流量到达前主动加载热点 Key,避免失效瞬间的并发冲击。
  3. 逻辑过期:缓存永不过期,通过后台异步线程更新,业务线程只读缓存。
实践建议:在 OpenAPI 契约中,热点 Key 应声明 x-cache-hotkey: true 和 x-cache-ttl-strategy: logical-expiry,以便网关层自动启用击穿保护策略。