keys_zone是为缓存键及元数据(如uri、状态码、过期时间、磁盘指针等)分配的共享内存区,不存响应体;应按预估并发缓存key数×1kb÷1024估算大小,常见合理范围为8m–256m,过小致伪未命中,过大则浪费且可能引发slab延迟。

fastcgi_cache_path 中的 keys_zone 参数,本质是为缓存键(key)分配一块共享内存区域,它不存响应体,只存元数据:比如 URI、状态码、过期时间、缓存命中状态、指向磁盘缓存文件的指针等。这块内存用得好,能大幅降低磁盘查找开销;配得过大或过小,都会带来明显副作用。
keys_zone 内存大小怎么估算
一个 key 的元数据平均占用约 512 字节(Nginx 官方文档及实测经验),但实际受 fastcgi_cache_key 复杂度影响——若你用了 $cookie_user_id$arg_sort$host 这类长变量拼接,单个 key 可能达 1–2 KB。保守起见,按 1 KB / key 估算更稳妥。
公式为:
keys_zone 大小(MB) ≈ 预估并发缓存 key 数 × 1 KB ÷ 1024
例如:
- 网站有 5000 个不同 URL(含常见参数组合)可能被缓存
- 每个 URL 平均对应 2–3 种状态(如 200/301/404)和不同
Accept-Encoding
→ 实际 key 数约 1.5 万
→ 推荐keys_zone=cache_fastcgi:16m
✅ 常见合理范围:8m–256m
⚠️ 小于 4m 容易频繁淘汰 key,导致“伪未命中”(key 找不到,但磁盘里其实有)
⚠️ 超过 512m 一般没必要,除非你有数百万级动态 URL 且全要缓存
keys_zone 与磁盘缓存的协同关系
keys_zone 是“索引”,磁盘路径(fastcgi_cache_path 指定的目录)是“数据本体”。二者必须配合:
-
索引必须足够快地定位数据:如果
keys_zone太小,key 频繁被踢出,Nginx 就得重新生成缓存(回源 PHP),失去缓存意义 -
磁盘空间不能只看
max_size:max_size=1g是硬上限,但真实占用还取决于inactive时间和缓存命中率。低命中率下,大量缓存写入又快速过期,磁盘 I/O 和碎片会升高 -
关键约束:
fastcgi_temp_path和fastcgi_cache_path必须在同一文件系统分区
→ 否则rename()操作失败,缓存写入会退化为拷贝,显著拖慢响应
实际配置建议(兼顾内存与磁盘)
# 共享内存区:按 2 万 key 估算,留余量设为 32m fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fastcgi_cache:32m inactive=30m max_size=2g; # 临时文件路径(必须和上面同分区) fastcgi_temp_path /var/cache/nginx/fastcgi/temp;
配套启用时注意:
-
fastcgi_cache fastcgi_cache;—— 名称需与 keys_zone 一致 -
fastcgi_cache_valid 200 302 10m;—— 缓存有效期不宜超过inactive,否则inactive不生效 - 加上
add_header X-Cache $upstream_cache_status;方便调试命中情况(HIT / MISS / EXPIRED / BYPASS)
如何验证是否配得合理
上线后观察两个指标:
-
nginx -s reload后,检查 error log 是否有cache zone "xxx" is too small报错 - 用
slabinfo(Linux)或pstack+gdb查看 Nginx worker 进程中ngx_slab_pool_t的使用率(需开启 debug 日志) - 更简单:定期执行
awk '/^fastcgi_cache:/ {print $2}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20看高频 key 是否稳定命中 —— 若 TOP20 key 的 HIT 率长期低于 60%,大概率是
keys_zone不足或inactive设太短
不复杂但容易忽略











