启用proxy_cache_lock可解决Nginx缓存并发写入冲突:需先在http块定义proxy_cache_path创建缓存区,location中配置proxy_cache、proxy_cache_lock on、proxy_cache_lock_timeout 5s及统一proxy_cache_key,并配合stale策略与权限管控。

要解决 Nginx 缓存层中并发写入导致的冲突(比如多个请求同时回源、重复生成缓存、响应不一致),核心是启用并合理配置 proxy_cache_lock 及其配套参数,而不是依赖外部同步机制。
必须先定义有效的共享缓存区
缓存锁功能依赖于一个已声明的缓存区,该区需在 http 块中用 proxy_cache_path 定义:
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)必须与后续proxy_cache指令保持一致 -
use_temp_path=off可避免临时文件拷贝,提升写入一致性 - 缓存目录(如
/var/cache/nginx/proxy_cache)需确保 Nginx worker 进程有读写权限,且不被其他脚本误删或占用
在 location 中启用并约束锁行为
锁只对「未命中缓存」(MISS)生效,需在具体 location 块中显式开启:
-
proxy_cache my_cache;—— 绑定缓存区 -
proxy_cache_lock on;—— 启用锁:仅首个 MISS 请求回源,其余等待 -
proxy_cache_lock_timeout 5s;—— 等待上限,超时后请求自行回源(防阻塞) -
proxy_cache_lock_age 1s;—— 控制锁释放时机,避免刚写入就立即被新请求覆盖
确保锁能真正覆盖目标请求
锁的作用范围由 proxy_cache_key 决定。相同 key 才共用一把锁:
- 默认 key 是
$scheme$proxy_host$request_uri,若 URI 含不同 query 参数(如/api/data?id=1和/api/data?id=2),则视为两个独立锁 - 如需统一锁定某类接口,可自定义 key:
proxy_cache_key "$host:/api/data"; - 避免在 key 中混入易变字段(如
$http_x_user_id或完整$args),否则会削弱锁效果 - 注意:
proxy_no_cache或响应头含Cache-Control: no-cache的请求会跳过整个缓存流程,锁不生效
配合 stale 策略降低锁压力
单靠锁不能完全规避后端延迟带来的排队问题。加入 stale 可让 Nginx 在更新缓存时仍返回旧内容:
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;-
proxy_cache_background_update on;—— 允许后台静默刷新过期缓存,用户无感知 -
proxy_cache_valid 200 302 10m;—— 合理设置有效期,从源头减少 MISS 频率


















