单个目录中有数百万个文件

单个目录中有数百万个文件

我需要一个文件存储解决方案,为一组 Web 服务器提供文件的读写功能。空间需求适中——目前大约为 2 TiB,但可能会增长到这个数字的两倍。现在使用的是 NFS,它看起来不错,直到我发现几乎所有文件都在一个目录中。考虑到目前大约有 1500 万个文件,总数可能会增长到 2000 万或 3000 万个,我担心 Linux 文件系统可能会在处理这么多文件时出现问题。

我建议修改应用程序,将文件拆分到几个子目录中,但当权者对此表示“不”。这似乎给我留下了两个选择:

  1. NFS。这可能是最简单的,但我不确定它能多好地处理目录中的文件数量。

  2. 云存储——这里指的是 Azure。我对云存储了解不够多,无法对预期性能发表意见。此外,我不知道是否需要进行哪种重写。云中的对象存储是否可以像 NFS 一样看起来像本地文件系统的一部分?

答案1

我刚刚意识到我从来没有发布过我最终做了什么来“解决”这个问题。

我构建了一个由四台服务器组成的 GlusterFS 集群。服务器 1 和 2 互相镜像。服务器 3 和 4 互相镜像。新文件交替写入 1/2 和 3/4 对。有点像用于文件存储的 Raid10。我认为 glusterfs 人员将其称为 2x2 集群。

这些卷由 lvm 管理并格式化为 XFS。

到目前为止,它表现良好。我们刚刚突破了 2500 万个文件大关,性能仍然令人满意。获取列表需要一段时间(大约 3 小时),但我每天只需要进行一次统计。根据 df,我们使用了总共​​ 8.0T 中的大约 5.2T,但请记住,由于镜像,实际使用的存储空间是这个数字的两倍。

感谢所有回答的人。这帮助我达成了妥协,这应该能维持一段时间。

答案2

他似乎认为这是一个系统问题,而且他的观点也并非完全错误。

一些在某种程度上,是的,旧文件系统在处理数百万个文件方面确实很糟糕;新文件系统的做法不同。例如,ext2 和 FAT 使用简单的线性文件列表,因此可扩展性问题确实是 ext2 和 FAT 的问题,它们随后在 ext4 和 NTFS 中进行了改进,使用 HTrees 或 B+trees。

(然而,最终文件系统的设计只能做到这么多——我怀疑优化一个通用文件系统来处理服务器上每个目录的数十亿个文件并不容易。仍然可用于桌面计算机上每个目录的数十个文件,而无需太多开销......)

但使用文件系统的方式也很重要。即使你有数百万个文件,例如 XFS,直接通过精确路径查找可能仍然相当快,因为​​它们只涉及读取目录数据的一小部分;但尝试列表相比之下,目录会慢得多。因此,你的程序应该设计为永远不需要列出整个目录,但要确切知道它需要哪些文件。

(打个比方,如果您使用 SQL 数据库,那么您已经知道搜索数据的正确方法是让服务器端查询“SELECT WHERE this=that”完成这项工作 - 您通常不会每次都尝试检索整个表,然后将其归咎于网络太慢。)

NFS。这可能是最简单的,但我不确定它能多好地处理目录中的文件数量。

NFS 本身不存储目录列表,它只提供对偏僻的“存储”文件系统。

因此,如果您的所有操作仅处理精确的路径(即读取此特定文件,写入此文件),那么 NFS 本身的功能应该与您的问题完全无关,因为 NFS 永远不需要看着完整的文件列表——它只会将请求的精确路径转发到文件服务器,其中 NFS 服务器的磁盘文件系统(例如 zfs 或 ext4)需要担心处理整个目录列表。

换句话说,您只是将问题转移到另一台机器上,但那里的问题仍然完全相同。(尽管 NFS 文件服务器当然可以使用比 Web 服务器上使用的文件系统更好地处理许多文件的文件系统,但您也可以在本地执行此操作。)

我能设计出的任何将文件分解到多个目录之间的策略都需要更改代码,而项目经理不愿意做除了最微不足道的更改之外的任何事情。

最简单的改变就是使用文件名本身的一部分它将成为子目录名称,因为这使得以后可以轻松找到文件 - 只需对文件名应用与存储时相同的转换即可。

看一下它的.git/objects/工作原理。它可以积累许多目标文件(特别是如果你回到 Git 还没有 packfile 的时候),因此它们会根据对象 ID 的前 2 位数字分成子目录。

例如,Git 对象c813a148564a5..位于objects/c8/13a148564a5..,使用带有 8 位前缀的一级子目录 - 有 256 个可能的子目录,每个子目录中的文件数量减少约 256 倍(例如,在 1000 万个对象的存储库中,每个目录只有约 40k 个文件)-软件只需知道每个对象的名称,就能准确地知道在哪里找到它。

如果您想要将文件分散开来,则可以使用更长的子目录名(例如,12 位表示 1/4096),甚至可以创建第二级子目录。

如果名称分布均匀(基于哈希的名称通常都是这样),这种方法效果最好。如果您的文件名往往以相同的文本开头,则应该对名称进行哈希处理以避免这种情况(并将真实名称与哈希名称的映射存储在数据库中)。

相关内容