if (!local.get(key, () -> redis.get(key))) {
// 回源前先 singleflight 合并同 key 请求
}
缓存过期那一刻,数据库 QPS 从 800 冲到 3.2 万,连接池直接耗尽,50 台实例每台都在回源同一个 key。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:本地缓存和 Redis 同时失效,每台实例各自查库,没有合并请求。回源前也没有再查一次 Redis,第一个请求还没写回时其他请求已经出发。
围绕「多级缓存回源放大」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
处理上按这个顺序:本地加 singleflight 同 key 只放一个请求出去;Redis 层加短锁 拿到锁的实例负责回源;热点 key 提前异步刷新 不要等过期才回源。
确认没问题再收工,同样让热点 key 过期,数据库 QPS 峰值只有 1200,持续两秒后回到正常水位。
