proxy_cache_lock 不能防止缓存击穿,仅对相同缓存 key 的并发 MISS 请求串行化回源;需同时满足 proxy_cache_path 定义 keys_zone、location 中启用 proxy_cache 和 proxy_cache_lock on 三前提,且需统一 cache_key、过滤动态参数与 Cookie 差异,并配置 lock_timeout、use_stale 和 cache_valid 才能有效协同。

proxy_cache_lock 本身不能“防止缓存击穿”,它只能在缓存未命中(MISS)时,把同一缓存 key 的并发请求串行化——只放行第一个去回源,其余等待结果写入后直接读缓存。要让它在高并发瞬间真正起效,必须满足几个硬性前提,并配合其他策略协同工作。
必须配齐的基础三要素
缺一不可,否则 lock 完全不触发:
- 在 http 块 中明确定义
proxy_cache_path,带keys_zone(如my_cache:10m),这是锁的共享内存载体 - 在目标 location 块 中启用缓存:
proxy_cache my_cache - 在同一 location 中开启锁:
proxy_cache_lock on
若请求因 Cache-Control: no-cache、proxy_no_cache 规则或 Nginx 判定为 bypass,则跳过整个缓存流程,lock 不介入。
让锁真正覆盖住并发请求
锁只对「完全一致的缓存 key」生效。key 不同,就等于没锁。常见导致 key 分裂的情况:
-
proxy_cache_key包含动态参数:默认含$args,/api/user?id=1和/api/user?id=2就是两个 key。应显式剥离无关参数,例如:proxy_cache_key "$scheme$host$uri";(忽略 query 和部分 header) - 前端加了随机参数(如
?t=1713086520或?v=2.3.1),需统一过滤 - Cookie 或认证头差异:登录用户带
Cookie: session=abc,游客不带,默认 key 就不同。应配合proxy_ignore_headers Set-Cookie和精简 key 使用
控制等待行为与失败兜底
光有 lock 不够,超时和降级决定实际体验:
-
proxy_cache_lock_timeout 5s:推荐设为 3–8 秒。太短,等待请求快速超时并发回源;太长,用户明显卡顿 -
proxy_cache_use_stale error timeout updating http_500...;:当首个请求回源失败、超时或正在更新时,允许立即返回旧缓存(stale),避免全部排队或集体降级失败 -
proxy_cache_valid 200 302 30s;:给热点接口设合理有效期,MISS 越少,lock 竞争越弱。静态资源可设数小时,API 接口建议至少 30 秒
验证是否真实生效
别靠猜测,用响应头确认:
- 在 location 中加:
add_header X-Cache-Status $upstream_cache_status; - 用
curl -I发起两次紧邻请求:
首次应返回X-Cache-Status: MISS,
第二个请求若返回HIT,说明锁成功阻塞并复用了结果;
若仍为MISS,说明 key 不一致或配置未生效











