proxy_cache_lock 通过串行化相同 cache key 的并发请求防止缓存击穿,但需配合缓存区定义、location 启用、key 统一、超时控制及 stale 兜底等完整配置才能生效。

proxy_cache_lock 本身不“防止击穿”,它只在缓存未命中(MISS)时,对完全相同 cache key 的并发请求做串行化:放行第一个去回源,其余等待结果写入缓存后直接读取。真正稳住后端的,是一整套协同配置——缺一不可。
缓存基础必须搭牢
没有缓存区、没启用缓存、没触发 MISS,proxy_cache_lock 就不会启动,形同虚设:
-
在
http块中定义缓存路径和共享内存区:proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=my_cache:512m inactive=3h use_temp_path=off;
-
keys_zone=my_cache是后续所有指令引用的名称,512MB 内存约支持 400 万个 key - 确保
/var/cache/nginx/proxy_cache目录存在,且 Nginx 进程有读写权限(注意 SELinux 或 umask 限制)
-
-
在目标
location中明确启用缓存:proxy_cache my_cache;
这是 lock 生效的硬前提。没这句,其他配置全无效。
锁要真正锁住同一类请求
key 不一致,就等于没锁。热点接口常因参数、Header、Cookie 差异被拆成多个 key,导致并发回源照旧:
-
默认
proxy_cache_key含$request_uri,/api/hot?id=1和/api/hot?id=2是两个独立 key
→ 改用剥离 query 参数的写法:proxy_cache_key "$scheme$host$uri";
前端加随机参数(如
?t=1718942840、?v=2.5.0)会人为制造 key 分裂
→ 同样通过自定义 key 忽略-
登录态请求含 Cookie 或
AuthorizationHeader
→ 配合:proxy_ignore_headers Set-Cookie Vary;
并避免在 key 中引入
$cookie_*或$http_*
设好等待底线与失败兜底
lock 只管“等”,不管“等不来”。后端慢、失败或超时,等待中的请求不能干耗着:
-
控制等待时长:
CPA Update - Secure CLI Proxy API Maintenance下载安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
proxy_cache_lock_timeout 5s;
- 太短(如 1s),等待请求快速放弃锁,并发回源重现
- 太长(如 30s),用户明显卡顿,还可能引发客户端重试雪崩
- 推荐设为后端 P95 响应时间的 1.2–1.5 倍(例如 P95 是 3.2s,设 4s)
-
兜底返回旧缓存:
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
当首个请求回源出错、超时或正在更新时,后续请求可立即返回 stale 缓存,不排队、不穿透、不空白页
-
延长缓存有效期,减少 MISS 次数:
proxy_cache_valid 200 302 30s; # API 类 proxy_cache_valid 200 1h; # 静态资源类
验证是否真实生效
别靠猜测,用实际观测确认:
-
在
location中加响应头:add_header X-Cache-Status $upstream_cache_status;
-
用
curl -I查看:- 首次请求应返回
X-Cache-Status: MISS - 紧随其后的并发请求应返回
HIT(说明锁成功复用)或仍为MISS(说明 key 不一致或配置未生效)
- 首次请求应返回
-
压测验证后端日志:
ab -n 20 -c 10 http://your.site/api/hot?id=123
开启 lock 后,后端应仅记录 1 条访问,而非 10 条
不复杂但容易忽略










