proxy_cache_lock 实现削峰的核心是只放行一个并发miss请求回源,其余等待或返回旧缓存,将千次回源压至1~2次;需配置keys_zone、启用缓存、统一cache_key、控制响应头,并配合lock_timeout与use_stale策略。

用 proxy_cache_lock 实现极端并发削峰,核心不是“锁住所有请求”,而是让大量并发 MISS 请求中,**只放行一个去后端取数据,其余要么等待结果、要么退而求其次返回旧缓存**——从而把原本可能上千次的回源,压到 1~2 次。它不消灭并发,而是重排并发,是 Nginx 层最轻量、最高效的削峰手段之一。
必须先让锁真正生效
很多配置看似开了 lock,实则完全不触发,原因往往在基础环节缺失:
- 没定义
proxy_cache_path和keys_zone:例如proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g;——keys_zone是锁的共享内存载体,没它,lock 形同虚设 - 没在 location 中启用缓存:
proxy_cache my_cache;—— 不启用缓存,就没有 MISS,自然不进锁逻辑 - 缓存 key 不统一:默认
$request_uri带参数,/api/user?id=1和/api/user?id=2就是两个 key;应显式控制,如proxy_cache_key "$host:/api/user";或"$scheme$host$uri"(去掉$args) - 响应被绕过缓存:后端返回
Cache-Control: no-cache、或命中proxy_no_cache规则、或含Set-Cookie且未配proxy_ignore_headers Set-Cookie,都会跳过整个缓存流程
用 timeout + stale 控制削峰节奏
proxy_cache_lock_timeout 决定“等多久”,proxy_cache_use_stale 决定“等不到时怎么办”。两者配合,才能应对极端场景:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
-
proxy_cache_lock_timeout 5s;:设为后端 P95 响应时间的 1.2–1.5 倍(如后端 P95 是 4s,可设 5s)。太短(如 1s)会导致大量请求几乎立刻放弃锁、集体回源;太长(如 15s)会让用户明显卡顿,还可能引发客户端重试雪崩 -
proxy_cache_use_stale updating error timeout http_502 http_503;:这是削峰的关键退路。只要首个请求正在回源(updating),后续请求就可直接返回旧缓存;若它超时或失败,也允许返回陈旧内容,避免全部排队或降级为空白页 - 搭配
proxy_cache_background_update on;:首个请求写完缓存后,Nginx 在后台静默刷新,不影响前端响应;用户看到的是“旧但可用”的内容,体验无感
从源头减少锁竞争频次
削峰效果上限,取决于每秒产生多少个真正需要锁的 MISS。降低 MISS 率,比调优 timeout 更治本:
-
proxy_cache_valid 200 302 30s;:对 API 接口设 30 秒已能显著缓解瞬时压力;静态资源可设为 1h 或更长 - 避免无意义参数干扰 key:前端加的
?t=1713086520、&v=2.3.1必须在proxy_cache_key中剔除,否则每个请求都是独立 key,锁完全失效 - 统一身份上下文处理:带登录态的接口,若用
$cookie_session入 key,游客和会员就无法共享锁;应剥离用户标识,或改用服务端本地缓存+限流兜底
验证锁是否真实起作用
别靠猜测,用可观测手段确认:
- 加响应头:
add_header X-Cache-Status $upstream_cache_status;,压测时看状态组合:首个请求是MISST(触发回源),紧随其后的并发请求应出现HIT(复用结果)或STALE(返回旧缓存),而非全是MISS - 查后端日志:用
ab -n 100 -c 50压测同一 URL,开启 lock 后,后端 access log 应仅记录 1~2 行,而不是 50 行 - 观察磁盘缓存文件生成:缓存路径下对应 key 的文件是否只创建一次,且后续请求读取的是同一文件










