Appearance
Redis 缓存击穿案例:热点商品过期后为什么数据库会被瞬间打满
缓存击穿是很经典的问题,但真正到线上时,很多人还是会被现象迷惑。
因为它看起来像:
- Redis 没挂
- 应用也没挂
- 但数据库突然被压得很厉害
场景
商品详情页有一个热点商品,平时大量请求直接走 Redis。
某次活动期间,这个热点 Key 正好过期,结果短时间内大量请求同时回源数据库,随后出现:
- 商品详情 RT 飙升
- 数据库连接数快速上涨
- 部分接口开始超时
先说结论
缓存击穿的典型链路通常是:
- 热点 Key 失效
- 大量并发请求同时发现缓存未命中
- 请求一起回源数据库
- 数据库变慢后,上游线程池和连接池继续被拖住
所以它不是“缓存没命中一次”这么简单,而是:
- 热点流量在短时间内失去了缓冲层
一、怎么判断是不是缓存击穿
更实用的判断信号包括:
- 某个热点接口 RT 突然升高
- Redis QPS 没明显下降,但该 Key 命中率突然掉了
- 数据库某张表的读流量瞬间上升
- 连接池等待时间明显变长
如果这些现象是同时出现的,就要高度怀疑:
- 热点缓存失效后大量回源
二、为什么热点 Key 最危险
因为普通 Key 过期,影响的是少量请求。
热点 Key 过期,影响的是:
- 一大批正在同时访问同一份数据的请求
也就是说,同样是一次缓存未命中:
- 冷数据可能只多打一次数据库
- 热点数据可能瞬间把数据库打穿
三、真实场景里最容易漏掉的点
1. 不是所有高并发都叫缓存击穿
如果是很多不同 Key 同时失效,更像是:
- 批量过期
- 缓存雪崩
如果是一个或少数几个热点 Key 出问题,才更像典型击穿。
2. 数据库慢不一定是数据库自身问题
很多时候数据库变慢只是结果,不是起点。
真正起点可能是:
- 一个超热点商品的缓存过期
3. 加大数据库连接池通常不是根治
如果回源流量没有被控住,只是把连接池调大,往往只是把数据库更快打满。
四、一个更实用的排查顺序
第一步:找出是不是热点 Key
先确认:
- 是不是单个商品、单个店铺、单个配置在抖
如果问题集中在极少数 Key,上来就可以往热点方向查。
第二步:看缓存命中率变化
重点不是看 Redis 整体有没有问题,而是看:
- 关键 Key 对应的业务命中率有没有突然下降
第三步:看数据库读流量和慢 SQL
要确认回源后数据库是:
- 只是读流量升高
- 还是已经开始出现慢 SQL 和连接等待
第四步:看上游线程池有没有被拖住
热点回源如果持续一段时间,很容易进一步引发:
- 线程池堆积
- 接口整体变慢
五、治理方式怎么选更稳
1. 热点 Key 互斥重建
最常见思路是:
- 第一个请求负责回源重建
- 其他请求等待短时间结果或直接走兜底
这样能避免大量并发同时打数据库。
2. 逻辑过期
有些极热点数据不适合严格依赖物理过期。
更稳妥的方式是:
- 缓存数据允许短时间旧一点
- 后台异步刷新
3. 过期时间打散
如果一批热点数据统一时间过期,风险会更大。
适当加随机值可以降低集中失效概率。
4. 本地缓存或多级缓存
对于极热点读场景,可以在 Redis 之外再增加一层更轻量的缓冲。
5. 做好限流和降级
真正的大促场景里,只靠缓存策略还不够,往往还要配合:
- 接口限流
- 数据降级
- 静态化或预计算
六、一个典型复盘怎么写
比较完整的复盘通常会写清楚:
- 哪个热点 Key 失效了
- 当时并发有多大
- Redis 命中率怎么变的
- 数据库读流量和连接数怎么变的
- 最后是通过互斥重建、逻辑过期还是限流兜住的
这样下次再遇到类似问题,团队才不至于从零开始排查。
一句话总结
缓存击穿最危险的地方,不是“少了一次缓存命中”,而是:
- 热点流量在同一时间一起回源
只要把热点识别、互斥重建、逻辑过期和限流兜底这几层搭起来,风险就会明显小很多。