nginx通过proxy_cache_lock等配置可将缓存未命中时的后端并发请求数压至接近1个:启用proxy_cache_lock on并设timeout,配合use_stale updating、cache_min_uses、bypass及background_update实现协同回源与平滑更新。

Nginx 缓存未命中时,多个并发请求同时打到后端,容易引发“缓存击穿”和后端排队雪崩。关键不是压低请求数,而是让 Nginx 主动协调——只放行一个请求回源,其余等待已有响应,避免重复穿透。
启用缓存锁(proxy_cache_lock)
这是最直接有效的控制手段。它让 Nginx 在发现某 key 无缓存时,只允许第一个请求去后端取数据,其他同 key 请求暂停并等待,拿到结果后一并返回。
- 开启锁机制:
proxy_cache_lock on; - 设置等待超时(防止死等):
proxy_cache_lock_timeout 5s;(默认 5 秒,超时后降级为各自回源) - 配合
proxy_cache_use_stale updating;,让等待中的请求在后台更新完成前,可先返回旧缓存(若存在),进一步缓解压力
限制单次请求才缓存(proxy_cache_min_uses)
避免为偶发、低频请求浪费缓存空间和锁资源,减少无效锁竞争。
-
proxy_cache_min_uses 2;
表示同一 key 至少被访问 2 次,Nginx 才会将其写入缓存。首次 MISS 不缓存,第二次再 HIT 才真正生效。这对冷启动或爬虫试探类请求很友好。
区分敏感路径,主动跳过缓存锁
对带用户身份、会话或实时性极强的接口(如 /api/user/、/api/order/status),锁机制反而可能造成跨用户响应污染或延迟升高。
- 使用
proxy_cache_bypass $cookie_session_id;或proxy_cache_bypass $arg_token;
显式绕过缓存(及锁),让这类请求直连后端,不参与锁竞争 - 同时配
proxy_no_cache $cookie_session_id;,确保响应也不被缓存
配合后台更新(proxy_cache_background_update)
当缓存即将过期时,Nginx 可在后台悄悄刷新,而前台继续返回旧内容。这样既保持响应速度,又避免大量请求在同一时刻因 EXPIRED 而集体回源。
-
proxy_cache_background_update on;
需与proxy_cache_use_stale updating;搭配使用才生效
这些配置组合起来,能把未命中时的后端并发请求数从 N 个压到接近 1 个,排队现象基本消失。











