proxy_cache_lock不能解决缓存穿透,仅缓解缓存未命中时的并发回源(惊群效应):首个请求回源写缓存,其余等待锁释放后直接读取;需配合proxy_cache、统一cache_key、proxy_cache_lock_timeout及proxy_cache_use_stale才生效。

proxy_cache_lock 是 Nginx 缓存模块中用于解决“缓存穿透”和“惊群效应”的关键机制,它通过锁机制确保同一缓存 key 在未命中时,只允许一个请求回源拉取内容并写入缓存,其余并发请求则等待该缓存生成完成后再直接读取,而非各自发起后端请求。
proxy_cache_lock 的核心作用
当多个请求同时访问一个尚未缓存的资源(cache miss)时,若不做控制,所有请求都会穿透到上游服务器,造成瞬时压力激增(即“惊群”)。启用 proxy_cache_lock 后,Nginx 会为该 key 加锁:
- 首个请求获得锁,执行 proxy_pass 回源,完成后写入缓存并释放锁
- 其他并发请求被阻塞(默认最多等待 5 秒,由 proxy_cache_lock_timeout 控制),待锁释放后直接从缓存读取
- 若锁等待超时,这些请求将绕过锁机制,各自回源(避免无限等待)
如何正确启用和配置
仅开启 proxy_cache_lock 不足以生效,需配合基础缓存配置使用:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 必须已定义 proxy_cache 并在 location 中启用(如 proxy_cache my_cache)
- 在对应 location 块中添加 proxy_cache_lock on;
- 建议显式设置 proxy_cache_lock_timeout 5s;(默认值即 5s,可根据后端响应时间调整)
- 注意:该指令仅对 cache miss 生效;cache hit 或 cache bypass 场景不参与锁逻辑
常见误区与注意事项
这个机制容易被误用或忽略细节:
- 不是分布式锁:proxy_cache_lock 是进程级(worker 级)内存锁,仅在同一 Nginx 实例内有效;多实例部署需配合共享缓存(如 shared memory zone)或外部协调机制
- 不保证强一致性:锁只控制“首次写入”,不阻止缓存过期后多个请求同时回源;需结合 proxy_cache_valid 和 proxy_cache_revalidate 优化
- 与 proxy_buffering 冲突风险:若关闭 buffering(proxy_buffering off),lock 可能失效,因响应流式传输导致无法完整缓存,建议保持 buffering 开启
验证是否生效的小技巧
可通过日志和简单压测观察行为:
- 开启 log_format 记录 $upstream_cache_status,看到大量 MISS 后紧跟 HIT,且并发请求日志时间戳高度集中,说明 lock 起作用
- 用 curl -H "Cache-Control: no-cache" 发起多线程请求(如 ab 或 wrk),对比开启/关闭 lock 时后端 access log 的请求数量差异
- 注意:若 upstream 返回了不可缓存响应(如 Cache-Control: private/no-store),lock 也不会触发










