![在一个目录中存储数千个文件](https://linux22.com/image/28499/%E5%9C%A8%E4%B8%80%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%AD%E5%AD%98%E5%82%A8%E6%95%B0%E5%8D%83%E4%B8%AA%E6%96%87%E4%BB%B6.png)
我有一个正在检查性能问题和错误的网站,我遇到了一个缓存代码,该代码将数千个文件缓存到一个目录中。
我知道这不好,I/O 会降低,而且我还听说了潜在的 inode 问题。
我知道如何修复缓存代码,但问题是此时修复将非常昂贵。
问题:如果我像现在这样生活,最坏的情况是什么?网站会发生什么? (目前这一单个缓存目录有 400K 个文件)
我是 Ubuntu 新手。我知道这可能是一个题外话。但我认为这是一个“系统”问题,它不属于 stackoverflow 的“编程”部分。
谢谢!
更新:文件系统是UFS
答案1
情况有些令人惊讶。超高速文件系统对于生产 Linux 安装来说是一个不寻常的文件系统。 Linux 下的 UFS 写访问通常需要在内核中显式启用,因为它已被被认为是实验性的很多年了:
CONFIG_UFS_FS_WRITE:UFS 文件系统写入支持(危险)
如果您想尝试写入 UFS 分区,请在此处选择 Y。这是实验性的,因此您应该事先备份 UFS 分区。
与许多传统文件系统一样,UFS 在目录中使用顺序文件查找。这确实会导致包含许多文件的目录的性能问题,因为搜索时间随着文件数量线性增长。在 BSD 中,UFS 通常是默认文件系统,这个问题直接导致了迪哈什,目录的哈希表查找,这显着提高了性能。
据我所知,Linux下的UFS支持不使用Dirhash。因此,随着目录中文件数量的增加,您可能会遇到越来越多的性能问题。就顺序访问而言,400K 文件已经很多了,并且您可以预期性能会受到显着影响。
在子目录之间分割文件可以有效地管理顺序访问问题。或者,您可以迁移到支持更复杂的文件存储结构的文件系统。例如,XFS实施大型目录的快速文件访问通过使用B+树。
您的第二个问题是关于索引节点。通常,文件系统上的 inode 数量是固定的,这通常是文件系统创建时可用空间量的函数。例如,/etc/mke2fs.conf
保存 ext 文件系统的默认 inode 比率(每 x 字节的 inode 数量)。
通常,这个数字远远大于您可能创建的文件数量,因此不必担心。但是,您可以使用 检查您的 inode 使用情况df -i
。如果索引节点限制实际上可能是一个问题,那么弄乱目录不会对你有帮助,因为索引节点是一个文件系统范围的概念,独立于目录。在这种情况下,您将被迫重新创建文件系统,并适当地设置 inode 参数 ( -i
) mkfs
。
答案2
在普通的 UNIX(基于索引节点)文件系统(包括 UFS)上,可以合理地近似地说您创建的每个文件或目录都使用一个索引节点。在一个目录中包含大量文件并不会改变这一点。
您描述的方法的常见问题是:
- 文件系统使用哈希或树型数据结构进行目录查找,以加快搜索和创建速度,单个目录中的文件越多,速度就越慢。对于散列,当发生冲突时,这种减速会非常明显。
- 典型的 unix 命令有问题(特别是
ls
排序和 shell glob 扩展),尽管通常早在文件系统速度减慢之前就出现了问题。 - 随着目录获得新文件,分配更多的块,它会变得越来越碎片,需要更多的磁盘IO来访问。
更现代的文件系统 (ext3/4) 使用类似 B 树的数据结构来保持目录排序,作为磁盘数据的一部分。我相信 UFS 实现使用内存哈希(基于 FreeBSD 使用和文档,我对 Linux 上的 UFS 没有太多直接经验),因为磁盘格式不使用哈希。
这里有一些很好的 UFS 信息和链接:https://serverfault.com/questions/53416/max-total-files-in-a-directory-in-freebsd-6-ufs
最可能的最坏情况是在某些时候您在访问该目录时会遇到明显且不断恶化的速度减慢。当它达到这一点时,修复起来将会很乏味(根据我在爆炸的 sendmail 队列方面的经验)。
我鼓励您监视(并绘制图表)您的系统等待时间,了解一下iotop
,slabtop
如果你还不知道的话。
如果可能的话,我还建议您尝试一些简单的实验,对缓存目录中创建 1000 个文件的时间进行计时,并与空目录中的文件进行比较。