缓存击穿是热点key过期瞬间大量并发请求穿透至数据库导致CPU飙升,需联动分析请求行为、缓存结构与数据库负载:一查keyspace_misses与TTL集中归零;二抓高频高代价回源SQL;三验空结果缓存、分布式锁及逻辑过期机制;四排查客户端本地缓存、网关bypass或定时清缓存等上游穿透。

缓存过期瞬间导致后端数据库 CPU 飙高,本质是“缓存击穿”问题——热点 key 失效后,大量并发请求同时穿透到数据库。排查不能只盯着 Redis 过期时间,而要从请求行为、缓存结构、数据库负载三者联动分析。
一、确认是否真是“过期瞬间”引发的击穿
很多所谓“过期导致 CPU 飙高”,实际是缓存未命中率突增(如客户端本地缓存批量失效、Redis 分片不均),而非 Redis 自身 key 过期。先验证真实过期行为:
- 查 Redis 的 keyspace_misses 是否在 CPU 飙高时刻同步陡升(
redis-cli info stats | grep keyspace_misses),且增幅与数据库 QPS 增长节奏一致 - 用
redis-cli --scan --pattern "your:hot:key:*" | xargs -I{} redis-cli ttl {}抽样检查热点 key 的剩余 TTL,看是否存在集中归零现象 - 比对监控时间线:CPU 飙高起点是否精确匹配某批 key 的 EXPIREAT 时间戳(可通过 Redis 的慢日志或 AOF 日志回溯)
二、定位被击穿的具体 SQL 和数据表
击穿不是均匀打满数据库,而是集中在少数查询上。重点抓取“高频+高代价”的回源 SQL:
- 开启数据库 全量慢日志(MySQL 设
long_query_time=0;SQL Server 查sys.dm_exec_query_stats中total_worker_time排名靠前的语句) - 筛选特征:执行频率高、Rows_examined / Rows_sent 比值极大(例如扫 500 万行只返回 1 行)、无索引或 Using temporary/Using filesort
- 结合业务日志,确认这些 SQL 对应的 key 是否正是你预设的热点缓存 key(如
product:10086→SELECT * FROM products WHERE id = 10086)
三、检查缓存重建机制是否缺乏保护
CPU 飙高往往不是因为“查一次”,而是“多个请求同时查+同时写缓存”。关键看代码中是否有防击穿设计:
- 是否对空结果做了缓存(防御穿透干扰判断)?比如查不到商品,也写入
product:999999→null并设短 TTL - 重建缓存时是否加了分布式锁?没有锁会导致 N 个线程重复执行同一 SQL,N 倍放大数据库压力
- 是否用了“逻辑过期”而非物理过期?即 value 内嵌过期时间字段,由应用控制是否异步刷新,避免 TTL 到点集体失效
四、验证客户端与中间层是否引入额外穿透
Redis 本身命中率可能很高,但上游可能早已绕过它:
- 检查 Web 层或 SDK 是否启用了本地缓存(如 Caffeine),且设置了固定刷新间隔(如 30s reload),导致所有实例在同一秒批量失效
- 网关或 CDN 是否对某些请求头(如未登录用户、特定 UA)默认 bypass 缓存?这部分流量不会计入 Redis 命中统计,却直接压向 DB
- 是否有定时任务主动清空缓存(如凌晨刷新报表缓存),且未做分批次或错峰处理?


















