proxy_cache_lock 通过串行化同一缓存 key 的并发未命中请求来缓解缓存击穿,需确保锁得准(统一 cache key)、锁得住(正确配置缓存区、proxy_cache 和 proxy_cache_lock)、退得快(启用 stale 和 background update)、源头少(减少 miss),并用 x-cache-status 验证效果。

proxy_cache_lock 本身不“防止”缓存击穿,它只对同一缓存 key 的并发未命中(MISS)请求做串行化:放行第一个回源,其余等待结果写入后直接读缓存。要让它在高并发下真正起效,必须围绕“锁得准、等得稳、退得快、源头少”四点系统配置。
锁得准:所有请求必须落在同一个 cache key 上
锁按 key 绑定,key 不一致就等于没锁。默认 key 含 $request_uri,/api/hot?id=1 和 /api/hot?id=2 就是两个独立 key,数万请求会变成数万个回源。
- 对固定路径热点接口(如商品详情),统一 key:
proxy_cache_key "$scheme$host:/api/product"; - 更通用做法是剥离 query 参数:
proxy_cache_key "$scheme$host$uri";(丢掉$args) - 过滤前端随机参数(
?t=1716942840、?v=2.4.1)和易变 header(Authorization、User-Agent、Cookie) - 配合
proxy_ignore_headers Set-Cookie Vary;,避免响应因含Set-Cookie被跳过缓存
锁得住:三要素缺一不可
没有缓存区、没启用缓存、location 里没开 lock,机制完全不触发。
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 在
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:512m是核心,512MB 内存可支撑约 400 万个 key - 确保目录存在且 Nginx 进程有读写权限:
mkdir -p /var/cache/nginx/proxy_cache && chown www:www /var/cache/nginx/proxy_cache - 在目标
location中必须启用缓存:proxy_cache my_cache;
没这句,就没有 MISS,lock 就是摆设 - 在同一 location 中开启 lock:
proxy_cache_lock on;<br>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 越少,锁竞争越弱,系统压力越小。
- 给热点 API 设最低保鲜期:
proxy_cache_valid 200 302 30s; - 静态资源可延长至 1h 或更久
- 避免误配
proxy_no_cache、proxy_cache_bypass,或响应头含Cache-Control: no-cache、Set-Cookie(后者需显式忽略)
验证是否生效,别靠猜:在 location 中加 add_header X-Cache-Status $upstream_cache_status;,用 curl -I 查看响应头。首次应为 MISS,紧随其后的并发请求若出现 HIT,说明锁成功复用结果;若仍是 MISS,大概率是 key 不一致或基础配置缺失。










