秒杀商品详情接口在缓存过期的那一秒,数据库连接池被两百个并发请求占满,恢复后还要等十几秒才缓过来,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 只有个位数增长,接口延迟没有陡升,同一时刻只有一个请求在重建。
这里还有个坑。互斥锁一定要带过期时间,持锁进程挂掉才不会把缓存堵死;逻辑过期方案要接受短时间内读到旧数据。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
