秒杀商品详情接口在缓存过期的那一秒,数据库连接池被两百个并发请求占满,恢复后还要等十几秒才缓过来,Redis 是 6.2 单节点。

一开始怀疑是「没有本地缓存兜底,穿透量全落在 Redis 和数据库」,查了一圈,方向不对。

原因不止一个,得分开看。缓存失效后没有互斥,所有请求同时去重建。还有一种是重建逻辑要八百毫秒,窗口足够堆积请求。

少数情况下是热点 key 没有逻辑过期,只能等物理过期后重建。

动手时先确认回源风暴的时间点与并发量

redis-cli monitor | grep -c 'GET sku:1001'

随后用 setnx 实现重建互斥锁

redis-cli set lock:sku:1001 1 NX EX 5

没抢到锁的请求读旧值兜底

redis-cli get sku:1001:bak

热点商品改逻辑过期后台异步刷新

redis-cli expire sku:1001:bak 3600

别只看报错消失,验证要多做一步。缓存过期瞬间数据库 QPS 只有个位数增长,接口延迟没有陡升,同一时刻只有一个请求在重建。

这里还有个坑。互斥锁一定要带过期时间,持锁进程挂掉才不会把缓存堵死;逻辑过期方案要接受短时间内读到旧数据。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189