proxy_cache_lock 通过限制同一缓存key的并发回源请求防止数据库过载,但需配合缓存配置、统一key、合理超时及stale机制才能真正生效。

proxy_cache_lock 本身不“解决”爆库崩溃,它只在缓存未命中(MISS)的瞬间,把同一 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是后续所有配置引用的名称;use_temp_path=off避免临时文件拷贝,提升写入一致性。 - 确保磁盘路径存在,且 Nginx 进程有读写权限(Linux/macOS 下注意 SELinux 或 umask 限制)。
- 在目标 location 中必须启用缓存:
proxy_cache my_cache;
没这句,就不存在 MISS,lock 根本不会触发。
让锁真正生效:key 必须一致,否则等于没锁
锁不是全局互斥,而是按 cache key 一对一绑定。key 差一点,就各自回源:
- 默认 key 含
$args,/api/user?id=1和/api/user?id=2是两个独立 key,锁完全失效。 - 对热点接口(如商品详情、用户资料),显式统一 key:
proxy_cache_key "$scheme$host:/api/product";
或更通用的剔除干扰写法:proxy_cache_key "$scheme$host$request_uri";(忽略全部 query 参数) - 避免把 Cookie、随机 header(如
$http_x_trace_id)、时间戳参数(?t=1715446200)塞进 key;配合proxy_ignore_headers Set-Cookie Vary;,防止响应被跳过缓存。
设好超时与退路:不卡用户,也不压垮后端
lock 只控制节奏,不加速后端。超时和 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 200 302 30s;延长热点响应有效期,从源头减少 MISS 次数。
验证是否真起作用:别信配置,看行为
配完不验证,等于白配:
- 在 location 中加响应头:
add_header X-Cache-Status $upstream_cache_status; - 用
curl -I并发压测同一 URL,观察响应头:
首个请求应为X-Cache-Status: MISS,紧随其后的请求若出现HIT,说明锁成功复用结果;若连续多个MISS,说明 key 不一致或配置未生效。 - 检查 Nginx 日志中
$upstream_cache_status字段,重点关注UPDATING状态占比(高说明 lock 生效,过高则提示 timeout 偏短或 stale 未启用)。


















