proxy_cache_lock 不能单独解决缓存击穿,仅在同 key 瞬时未命中时生效,需结合 cache_path、proxy_cache、cache_key 优化、lock_timeout、stale 机制及日志验证构成完整防护链。

proxy_cache_lock 不能单独解决缓存击穿引发的回源雪崩,它只在“同一缓存 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)后续会被引用,大小按每 1MB 支持约 8000 个 key 估算
- 确保磁盘路径存在,且 Nginx 进程有读写权限(Linux/macOS 下注意 SELinux 或 umask 限制)
- 在目标 location 中必须启用缓存:
proxy_cache my_cache; —— 这是 lock 生效的前提
精准锁定:让同一类请求共用一把锁
锁不是全局互斥,而是按 cache key 绑定。key 不一致,就等于没锁:
- 默认 key 包含 $args,/api/product?id=1001 和 /api/product?id=1002 是两个独立 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
设好超时与退路:不卡用户,也不压垮后端
锁本身不加速后端,只控制并发节奏。超时和 stale 才决定系统是否稳得住:
- proxy_cache_lock_timeout 5s:推荐 3–8 秒。太短(如 1s),等待请求快速放弃锁并发回源;太长(如 30s),用户明显卡顿
- proxy_cache_use_stale error timeout updating http_500–504:当首个请求回源失败、超时或正在更新时,后续请求可直接返回旧缓存(stale),避免全部排队或降级失败
- proxy_cache_valid 200 302 30s:对 API 接口延长有效时间,从源头减少 MISS 次数;静态资源可设为 1h 甚至更久
验证是否真生效:别靠猜,看日志和响应头
配置完必须验证,否则等于没配:
- 在 location 中添加:
add_header X-Cache-Status $upstream_cache_status; - 用 curl -I 查看响应头:首次请求应为 X-Cache-Status: MISS,紧随其后的并发请求应出现 HIT(说明锁成功复用结果)或仍为 MISS(说明 key 不一致或配置未生效)
- 压测验证:用 ab -n 20 -c 10 并发请求同一 URL,开启 lock 后,后端访问日志应仅记录 1 条,而非 10 条











