单目录文件过多导致查找退化为线性扫描或哈希冲突加剧,使dentry查找从O(1)变慢,stat/open延迟上升,dcache压力增大引发锁竞争;levels=1:2通过两级哈希分散文件至4096子目录,平衡负载与路径深度。

levels 参数不改变单次缓存文件的磁盘检索耗时,但它直接决定海量缓存场景下整体 I/O 效率的上限——核心是防止目录项(dentry)查找成为瓶颈。
为什么单目录放太多文件会变慢
Linux 文件系统(如 ext4、XFS)在单个目录中维护成千上万个文件时,目录项查找会从 O(1) 退化为线性扫描或哈希冲突加剧。尤其当缓存键 MD5 值分布集中,或大量请求命中同一级目录时,stat/open 等系统调用延迟明显上升。
- 10 万文件堆在一个目录:ext4 下平均查找可能达毫秒级,影响高并发吞吐
- 目录项缓存(dcache)压力增大,容易引发锁竞争
- XFS 虽支持大目录,但未开启 dir_index 特性或碎片严重时仍会劣化
levels=1:2 是当前最均衡的选择
它把缓存键(MD5 哈希值)按固定规则拆解为路径层级,天然实现文件分散:
- 第一级取最后 1 位十六进制(0–f),共 16 个目录
- 第二级取倒数第 2–3 位(共 256 种组合),每级目录下平均承载数百个文件
- 最终路径形如 /cache/7/ab/cdef1234...,总子目录数达 4096 个
- 相比 levels=2 或 levels=1:1:1,它避免了深层嵌套开销,也规避了一级目录过载
搭配文件系统与挂载选项才能发挥效果
仅设 levels 不够,还需底层配合:
- 使用 XFS 或启用 dir_index 的 ext4,确保大目录查找高效
- 挂载时加上 noatime,nobarrier(SSD 场景)减少元数据写入
- 确保 cache 目录所在分区有足够 inodes(
df -i检查) - 避免将 cache 和系统日志等高频写入目录混放在同一逻辑卷
keys_zone 大小要与 levels 规划匹配
内存中的 keys_zone 存的是 key 元数据,不是文件本身;但它决定了 Nginx 能多快判断 HIT/MISS:
- 1MB ≈ 8000 个缓存条目,若缓存总量约 8 万 key,建议 keys_zone ≥ 10m
- 如果 levels 分散得当但 keys_zone 过小,会导致频繁 key 驱逐,反而增加磁盘 lookup 次数
- 重启后 keys_zone 清空,但磁盘文件仍在;此时首次访问需重建索引,短暂影响命中率



















