proxy_cache_lock 防缓存击穿需配合缓存区、key 控制、超时与 stale 策略:必须定义 keys_zone 并启用 proxy_cache;按 key 精准锁定,避免动态参数干扰;设 proxy_cache_lock_timeout 3–8s 及 use_stale 应对回源失败;通过 X-Cache-Status 和压测验证锁生效。

配置 proxy_cache_lock 防止高并发瞬间缓存击穿,关键不在“开开关”,而在于让锁真正生效、可控、有退路。它只对未命中缓存(MISS)的请求起作用,且必须配合缓存区、key 控制、超时与 stale 策略协同工作。
必须先定义缓存区并启用基础缓存
没有缓存区,proxy_cache_lock 完全不生效:
- 在
http块中定义共享内存缓存区,例如:proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
其中keys_zone=my_cache:10m是后续引用的关键名称,10MB 内存约支持 8 万个缓存 key。 - 在目标
location中启用缓存:proxy_cache my_cache;
这是 lock 生效的前提——没启用缓存,就不存在 MISS,自然不触发锁。
精准控制锁的作用范围
锁不是全局互斥,而是按缓存 key 一对一绑定。key 不一致,就等于没锁:
- 默认
proxy_cache_key是$scheme$proxy_host$request_uri,含 query 参数。因此/api/user?id=1和/api/user?id=2是两个独立 key,各自触发回源。 - 若想对某类接口统一加锁(如所有用户查询),应显式简化 key:
proxy_cache_key "$host:/api/user";
或剔除干扰参数:proxy_cache_key "$scheme$host$request_uri";(不带$args) - 避免将动态 header(如
$http_x_user_id)、Cookie 或随机参数(?t=123)加入 key,否则会人为制造 key 差异,削弱锁效果。
设置合理超时与 stale 回退策略
锁本身不解决后端慢的问题,超时和 stale 才是缓解压力的核心:
-
proxy_cache_lock_timeout 5s;—— 推荐设为 3–8 秒。太短(如 1s)导致等待请求快速超时并发回源;太长(如 30s)会让用户明显卡顿。 -
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;—— 当首个请求回源失败、超时或正在更新时,后续请求可直接返回旧缓存(stale),避免全部排队或降级失败。 - 搭配
proxy_cache_valid延长热点响应有效期,从源头减少 MISS 次数:proxy_cache_valid 200 302 30s;(API)proxy_cache_valid 200 1h;(静态资源)
验证锁是否真实生效
别靠猜测,用可观测手段确认:
- 在
location中添加响应头:add_header X-Cache-Status $upstream_cache_status; - 用并发工具(如
ab -n 20 -c 10)压测同一 URL,观察:- 首次请求返回
X-Cache-Status: MISS; - 紧随其后的请求返回
HIT(说明锁成功复用结果)或仍为MISS(说明 key 不一致或配置未生效); - 后端访问日志中应仅记录 1 条请求(而非 10 条)。
- 首次请求返回


















