proxy_cache_lock 通过“锁得准、等得稳、退得快、源头少”实现精准抗击穿:统一 cache key、启用缓存区与 lock、配置 stale 回退、减少 MISS,使并发请求串行回源。

要让 proxy_cache_lock 真正挡住高并发击穿,关键不是打开开关,而是让它“锁得准、等得稳、退得快、源头少”。它不解决缓存大面积过期(雪崩),也不防恶意穿透,只专注一件事:当同一资源缓存失效时,把成百上千并发请求压成一个回源,其余排队等结果——这是对抗击穿最轻量也最有效的第一道防线。
锁得准:所有请求必须落在同一个 cache key 上
锁按 key 绑定,key 不一致,等于没锁。默认 $scheme$proxy_host$request_uri 会把 /api/user?id=1 和 /api/user?id=2 当作两个 key,数万请求就变成数万个独立回源。
- 对固定路径的热点接口(如商品详情页、公告栏),统一 key:
proxy_cache_key "$scheme$host:/api/product"; - 更通用的做法是剥离 query 参数:
proxy_cache_key "$scheme$host$uri";(丢掉$args) - 过滤前端加的随机参数(
?t=1718614290、?v=2.4.0)、用户身份头($http_x_user_id)、Cookie 等易变字段 - 配合
proxy_ignore_headers Set-Cookie Vary;,避免响应因含Set-Cookie被跳过缓存
锁得住:三要素缺一不可
没有缓存区、没启用缓存、location 里没开 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 进程可读写:
mkdir -p /var/cache/nginx/proxy_cache && chown www:www /var/cache/nginx/proxy_cache - 在目标
location中必须启用缓存:proxy_cache my_cache;
没这句,就没有 MISS,lock 就是摆设 - 在同一 location 中开启锁:
proxy_cache_lock on;proxy_cache_lock_timeout 5s;(建议 3–8 秒:太短易放弃,太长用户卡顿)
等不起时有退路:stale 是保命配置
首个请求若超时、报错或慢得离谱,不能让其余请求干等或全部穿透。
- 允许返回旧缓存(即使已过期):
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - 搭配后台静默更新(可选):
proxy_cache_background_update on; - 对空响应也缓存,防穿透:
proxy_cache_valid 404 10s;
源头减压:减少 MISS 次数才是治本
MISS 越少,锁竞争越弱,系统越稳。
- 合理设置有效期:
proxy_cache_valid 200 302 30s;(API 类)proxy_cache_valid 200 1h;(静态资源) - 避免低频请求占用缓存空间:
proxy_cache_min_uses 2;(访问至少 2 次才缓存) - 用
$upstream_cache_status响应头验证效果:
第二个紧邻请求应返回HIT或STALE,而非MISS


















