keys_zone耗尽是缓存元信息占满共享内存,导致新缓存无法注册,可能引发500或crash;需检查内存使用率、key膨胀及loader异常,优化key设计并调优配置。

keys_zone 耗尽不是“缓存满了”,而是缓存元信息(key 的哈希索引、过期时间、文件路径等)占满共享内存区,导致新缓存项无法注册,Nginx 可能拒绝缓存、返回 500 或直接 crash(如 SIGSEGV)。排查需聚焦内存区本身是否真的不足、key 是否失控膨胀、以及加载行为是否异常。
确认 keys_zone 实际使用率与告警迹象
先查配置中定义的大小,再看运行时真实占用:
- 执行 nginx -T | grep "keys_zone" 查出当前 zone 名称和声明大小(如
keys_zone=my_cache:10m) - 用 ss -m | grep nginx 或 ipcs -m | grep nginx 查共享内存段实际分配量,对比是否接近上限
- 观察 error.log 中是否有 "cache manager process ... exited on signal 11"、"shmtx forced unlock" 或 "no memory in cache" 类日志
- 若频繁出现 "upstream sent too big header" 且伴随缓存失效,可能是 key 过长导致元信息溢出,而非响应头本身过大
检查 cache_key 是否失控膨胀
每个 key 的元信息固定消耗约 512B–1KB 内存。key 越长、越分散,zone 消耗越快:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 禁用高变长变量:删掉
$args、$query_string、$http_user_agent、$cookie_sessionid等;改用$host$uri或白名单参数(如"$host$uri?$(arg_id)&$(arg_type)") - 用 log_format 抓真实 key:
log_format cache_debug '$remote_addr - "$upstream_cache_key"';,配合 access.log 查看高频 key 长度与分布 - 特别注意 CDN 回源场景:原始 URL 带随机 t=、_r=、utm_ 参数,或埋点 header 注入长 trace-id,都会让一个逻辑资源生成数万不同 key
验证缓存加载器(loader)是否引发瞬时峰值
Nginx 启动或重载后,会批量扫描磁盘缓存并加载元信息到 keys_zone。若 key 过长或数量巨大,loader 可能在几秒内吃光 zone:
- 检查 proxy_cache_path 是否设置了 loader_threshold(默认 200)、loader_files(默认 200)、loader_sleep(默认 50ms)
- 若日志中发现重载后立刻 OOM 或 worker 退出,尝试调低 loader_files 至 50、增大 loader_sleep 至 200ms,缓解瞬时压力
- 对已有大缓存目录,可临时停掉 Nginx,用 find /path/to/cache -type f | wc -l 统计文件数,百万级缓存建议 zone ≥ 512MB
调整与监控双线并行
不能只加内存,要同步控 key、限生命周期、设兜底:
- 把 keys_zone 从 10m 提至 128m 或更高(估算:预期并发活跃 key 数 × 1KB)
- 加 inactive=30m 和 max_size=5g,避免冷 key 长期驻留;对动态接口设 proxy_cache_valid 200 5s
- 启用 proxy_cache_use_stale updating,防止锁等待期间全量回源压垮后端
- 部署 cron 定期执行 nginx -s reload 前先 nginx -t,避免配置错误触发 loader 异常加载










