proxy_cache_lock 通过串行化同一 cache key 的并发回源请求防缓存击穿,需配置缓存区、启用缓存与锁、统一 cache key、设置超时及 stale 退路,并用响应头和日志验证生效。

proxy_cache_lock 本身不“防击穿”,它只在缓存未命中(MISS)时,对同一 cache key 的并发请求做串行化:放行第一个回源,其余等待结果写入后直接读缓存。要让它真正起效,必须配齐基础、锁准 key、控好超时、留好退路。
必须先搭好缓存基础
缺一不可,否则 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:512m是核心,内存大小按每 1MB 支持约 8000 个 key 估算;目录需存在且 Nginx 进程有读写权限 - 在目标 location 块中启用缓存:
proxy_cache my_cache;
——没这句,就没有 MISS,lock 就是摆设 - 在同一 location 中开启 lock 并设超时:
proxy_cache_lock on;<br>proxy_cache_lock_timeout 5s;
——超时建议 3–8 秒:太短(如 1s)易放弃锁并发回源;太长(如 30s)用户明显卡顿
让锁真正锁住同一类请求
锁按 key 绑定,key 不一致就等于没锁。常见导致 key 分裂的情况:
- 默认
$request_uri含 query 参数 →/api/user?id=1和/api/user?id=2是两个 key
✅ 改用:proxy_cache_key "$scheme$host$uri";(丢掉$args) - 前端加随机参数(
?t=1716942840、?v=2.4.1)或 Cookie、Authorization 等 header 差异
✅ 统一收束 key:proxy_cache_key "$scheme$host:/api/user";
✅ 配合:proxy_ignore_headers Set-Cookie Vary;,避免响应因含Set-Cookie被跳过缓存
给等待加退路:stale 和 background update
首个请求可能慢、失败或超时,不能让其余请求干等:
- 允许返回旧缓存(即使已过期):
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - 可选后台静默更新(新内容写入不影响当前响应):
proxy_cache_background_update on; - 对空响应也缓存,防穿透:
proxy_cache_valid 404 10s;
验证是否真生效
别靠配置猜,用可观测手段确认:
- 在 location 中添加响应头:
add_header X-Cache-Status $upstream_cache_status;<br>add_header X-Cache-Lock $upstream_cache_lock;
- 用
curl -I发起两次紧邻请求:
首次应为X-Cache-Status: MISS,第二个若返回HIT或UPDATING,说明锁成功复用结果;若仍是MISS,说明 key 不一致或配置未加载 - 压测验证后端 access log —— 开启 lock 后应只记录 1 条回源日志











