缓存击穿导致首个请求响应延迟飙升,本质是热点key过期后仅一个请求重建缓存,其余阻塞或重复查库;排查需验证日志中“未命中→查库→写缓存”链路是否完整且耗时占比超80%。

缓存有效期失效后,首个请求等待过久,本质是“缓存击穿”在单点场景下的典型表现——热点 Key 刚过期,大量并发请求涌向数据库,而只有一个请求能成功重建缓存,其余请求要么阻塞等待,要么重复查询,导致响应延迟飙升。排查需聚焦“谁在等、等什么、为什么等得久”。
确认是否真为首个请求重建缓存
不是所有“慢请求”都是缓存重建触发的。先验证该请求是否确实承担了回源+写缓存的职责:
- 检查日志中是否有明确的「缓存未命中→查库→写入缓存」完整链路,且该链路耗时占总响应时间 80% 以上
- 对比同一 Key 的后续请求:若第二、第三个请求响应极快(
- 用 Redis 命令 ttl key 在过期前后实时验证,确认过期时刻与慢请求发生时刻吻合
定位重建过程中的性能瓶颈
即使逻辑正确,重建本身也可能拖慢首个请求。重点排查以下环节:
- 数据库查询慢:该 Key 对应的数据是否涉及多表 JOIN、全表扫描或未走索引?用慢查询日志或执行计划(EXPLAIN)确认
- 写缓存失败或延迟高:Redis 网络 RTT 是否突增?是否存在 Pipeline 阻塞、大 Value 序列化开销(如 JSON 嵌套过深)?
- 锁等待超时设置不合理:若使用互斥锁(如 SETNX + 过期时间),检查锁的 TTL 是否远小于业务查询耗时,导致锁提前释放、多个请求同时重建
验证锁机制是否真正生效
很多团队“加了锁”却没起效,常见失效点:
- 锁 Key 与业务 Key 不一致(例如锁用 user:123,但缓存 Key 是 profile:user:123)
- 未对锁设置自动过期时间,Redis 宕机后锁永久残留,后续请求全部卡死
- 业务代码在异常分支(如 DB 查询抛错)中未释放锁,造成死锁
- 使用本地锁(如 synchronized)而非分布式锁,在多实例部署下完全无效
观察并发请求行为模式
通过监控或日志统计同一秒内对该 Key 的请求数量和响应时间分布:
- 若出现“一个请求耗时 800ms,其余 9 个请求平均 750ms”,说明锁未生效或未等待锁释放就直接查库
- 若出现“一个请求耗时 800ms,其余请求均
- 若大量请求返回 504 或超时,可能是锁等待时间(如 tryLock(3, TimeUnit.SECONDS))设置过短,导致放弃等待直接回源











