proxy_cache_lock_timeout 是与 proxy_cache_lock on 配合使用的阈值,仅在缓存 MISS 时生效,决定后续请求等待锁释放后回源还是放弃排队自行回源,需权衡防击穿与用户体验。

proxy_cache_lock_timeout 不是独立生效的“超时开关”,而是决定等待请求能否“放弃排队、自行回源”的关键阈值。它必须和 proxy_cache_lock on 配合使用,且只在缓存未命中(MISS)时起作用。调优目标不是单纯延长或缩短时间,而是平衡“防击穿”与“用户体验”:太短,锁形同虚设;太长,用户卡顿明显。
明确 timeout 的实际触发逻辑
当多个请求同时访问一个未缓存或已过期的资源时:
- Nginx 放行第一个请求去后端取数据,同时为该 cache key 加锁
- 若首个请求在
proxy_cache_lock_timeout设定时间内完成并写入缓存,则所有等待请求直接读缓存返回 - 若超时仍未完成,Nginx 会放行**一个**新的等待请求去回源(注意:不是全部放行),其余继续等待或按策略处理
大规模并发下的推荐取值范围与依据
生产环境常见值为 3–8 秒,具体需结合后端响应稳定性判断:
- 后端平均响应 3–5s:足够覆盖绝大多数回源,避免无效等待
- 后端偶有慢查询或依赖外部服务(如数据库、第三方 API)→ 建议 6–8s:给后台更新留出缓冲,减少二次穿透
- 绝对避免设为 0 或 1s:会导致大量请求几乎立刻超时并发回源,击穿风险反而升高
- 不建议超过 10s:用户端感知延迟显著,尤其移动端易触发重试,可能引发雪崩式重试请求
必须同步配置的配套策略
单独调大 timeout 不能解决问题,需与以下机制联动:
-
启用 stale 策略:
proxy_cache_use_stale updating error timeout http_502 http_503;当锁等待中首个请求尚未完成,但已有旧缓存(stale),Nginx 可直接返回旧内容,大幅降低用户等待感 -
控制 cache key 粒度:确保相同业务语义的请求生成同一 key(例如统一忽略无意义 query 参数
v=xxx),否则 lock 对不同 key 无效 -
设置合理缓存有效期:
proxy_cache_valid 200 302 30m;减少 MISS 频次,从源头降低锁竞争概率
验证是否生效的简单方法
通过日志或响应头快速确认行为是否符合预期:
- 开启
add_header X-Cache "$upstream_cache_status";,观察并发请求是否出现MISST(首个请求)、MISS(超时后第二个回源)、HIT(后续请求命中新缓存)等状态组合 - 在后端 access log 中检查同一资源 URI 的请求频次:启用 lock 后,MISS 阶段应明显收敛为单个或极少量请求
- 用 ab 或 wrk 模拟 100+ 并发请求同一未缓存路径,对比开启/关闭 lock + timeout 前后的后端请求数量差异











