levels参数不缩短单次查找耗时,但通过将文件均匀分布到4096个子目录(如levels=1:2)缓解千万级小文件的目录寻址压力,使ext4/XFS查找保持常数时间;需配合高质量cache_key、充足keys_zone、禁用temp_path及SSD单独挂载等优化。

levels 参数本身不缩短单次文件查找耗时,但能从根本上缓解千万级小文件场景下的目录寻址压力——关键在于避免单目录堆积过多文件,让文件均匀落到成百上千个子目录中,从而把文件系统层面的线性扫描或哈希冲突控制在可接受范围。
选对 levels=1:2 是最稳妥的起点
它将缓存键(MD5 值)按固定规则拆解为三级路径:第一级用最后 1 位十六进制(0–f),共 16 个目录;第二级取倒数第 2–3 位(00–ff),共 256 个子目录;最终文件名用剩余部分。总叶子目录数为 4096 个。
- 即使缓存总量达 500 万文件,每个子目录平均仅约 1200 个文件,ext4 或 XFS 查找仍基本保持常数时间
- 路径层级不过深,避免了过多 stat 系统调用开销,比如 /var/cache/nginx/7/ab/cdef1234
- 比 levels=2(仅一级、256 目录)更分散,也比 levels=1:1:1(虽也是 4096 目录但分布易倾斜)更稳定
超大规模场景可升级到 levels=1:2:2
当缓存条目稳定超过 800 万,且观察到部分子目录文件数明显高于均值(可通过 find /path -type d -name "*" | xargs -I{} sh -c 'ls -A {} | wc -l' | sort -n),说明当前分层已接近负载上限。
阿里百炼大模型平台多人共享账号用量统计代理服务。解决公司共用账号时无法区分个人用量的问题。适用场景:1)部署用量统计代理;2)统计多人Token用量和调用次数;3)管理大模型API调用配额。
- levels=1:2:2 总共支持 16 × 256 × 256 = 104 万个叶子目录,单目录文件数可压至百以内
- 注意:路径变深(如 /cache/a/bc/def/...)会略微增加 open() 调用开销,但远小于单目录几万文件带来的 dentry 查找延迟
- 需同步检查文件系统 inodes 是否充足(df -i),XFS 推荐启用 dir_index 特性
配合 cache_key 设计才能真正均衡分布
levels 的效果高度依赖 cache_key 的哈希散列质量。如果 key 中含时间戳、随机 ID 或高熵字段,会导致大量缓存集中落在少数几个目录下,分层就形同虚设。
- 推荐构造方式:$scheme$host$uri$is_args$args,去掉 $request_time、$cookie_sessionid、$msec 等动态字段
- 可临时开启日志记录 $cache_key 和 $upstream_cache_status,再用脚本统计各子目录文件数量分布
- 若发现某一级目录(如 /cache/0/)文件数远超其他,说明 key 中存在前缀强相关性,需调整提取逻辑
别忘了底层和内存协同优化
只改 levels 不足以释放全部性能,必须同步调整其他关键参数:
- keys_zone 至少配到 20m:1MB ≈ 8000 个 key,千万级缓存建议 ≥16m~32m,防止 key 频繁驱逐引发额外磁盘 lookup
- use_temp_path=off:避免临时文件跨文件系统写入,减少一次 copy-on-write 开销
- 挂载选项加 noatime,nobarrier(XFS)或 noatime,commit=60(ext4),降低元数据更新频率
- cache 目录单独挂载 SSD 分区,不与系统日志、数据库混用同一逻辑卷










