proxy_cache_min_uses 不是缓存开关,设为2或3仅控制第几次响应才写入缓存,可显著减少长尾URI对keys_zone内存和磁盘IO的无效占用;需结合proxy_cache_lock及分层location配置才能真正生效。

proxy_cache_min_uses 不是缓存开关,设为 2 或 3 并不会让请求“不回源”,它只决定第几次响应才写进缓存——但这个细节能显著减少 keys_zone 内存被长尾 URI 占满。
为什么设成 2 就能拦住大量无效缓存
默认 proxy_cache_min_uses 1 意味着每个可缓存的响应(哪怕只访问 1 次)都会生成一个 cache key,并在 shared memory 中占一个 slot。而长尾请求如 /log?uid=123&t=1713224400456&r=abc123、/wp-admin/、/phpmyadmin/,URI 高度离散,key 几乎不重复:
- 每个 key 占用约 128 字节内存(含 metadata),1 万个长尾请求就吃掉 1.2 MB keys_zone
- 磁盘上还会为每个 key 创建对应文件,即使只有几 KB,IO 开销和 inode 消耗也不容忽视
- 这些 key 终身只被查 1 次,却长期驻留 inactive 期内,挤占真正高频内容(如首页、JS 包)的 slot
设为 proxy_cache_min_uses 2 后,前一次访问仍回源、仍查缓存(若已有副本仍可能 HIT),但响应体不落盘、key 不计入计数——相当于把“写入门槛”从“出现即存”变成“确认复访才存”。
哪些 location 必须单独配,不能全局一刀切
全站统一设 proxy_cache_min_uses 3 是典型误用:中频内容(如列表页每天被访问 2–4 次)永远卡在阈值外,既没缓存又持续回源。应按路径语义分层配置:
-
location ~* \.(js|css|png|jpg|gif)$:设proxy_cache_min_uses 2—— 过滤爬虫单次抓取,保留真实用户二次加载 -
location = /或location ^~ /api/config:保持proxy_cache_min_uses 1—— 天然高复用,无需预热 -
location ^~ /user/:设proxy_cache_min_uses 2或3—— 匹配用户回访行为,避免新注册用户的冷门 profile 被缓存 -
location ^~ /log或含随机参数路径:用map显式跳过缓存,例如proxy_no_cache 1,而非依赖 min_uses 被动过滤
不加 proxy_cache_lock,min_uses=2 就是假安全
单独设 proxy_cache_min_uses 2 只是“延后缓存”,不是“防并发”。若无锁机制,第 1 次和第 2 次同 URI 请求可能同时穿透,造成双倍回源压力:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 开启
proxy_cache_lock on后,第 1 次请求触发回源并加锁 - 第 2 次请求阻塞等待,不发往后端;锁释放后,响应写入缓存,此时自然满足 min_uses=2 条件
- 后续请求直接 HIT —— 实现“一次回源、多次服务”的闭环
- 务必配
proxy_cache_lock_timeout 5s,避免锁持有过久导致请求堆积
漏掉这一步,proxy_cache_min_uses 的调优效果会打五折以上。
怎么确认它真正在起作用
仅看日志或监控数字容易误判。最直接的方式是观察响应头与日志字段:
- 在
location块中加add_header X-Cache-Status $upstream_cache_status - 配合 Nginx 日志格式里记录
$upstream_cache_status,重点关注三类状态: -
MISS:未命中缓存,且本次响应未写入(常见于第 1 次访问 +min_uses 2) -
HIT:成功从缓存返回(说明已跨过 min_uses 门槛) -
EXPIRED或STALE:命中但过期/陈旧,证明缓存已存在,只是未及时刷新
如果大量 /log? 类请求始终显示 MISS 且从不出现 HIT,说明它们被有效拦截;但如果某静态资源反复 MISS 却不见 HIT,就要检查是否 proxy_cache_key 里混入了不可缓存参数(如 $args 中的 utm_source),导致 key 无法复用。










