根据这个纸在 Facebook 的 Haystack 上:
“由于 NAS 设备管理目录元数据的方式,将数千个文件放在一个目录中效率极低,因为目录的块图太大,无法被设备有效缓存。因此,检索单个图像通常需要进行 10 次以上的磁盘操作。在将目录大小缩减为每个目录数百个图像后,生成的系统通常仍需要进行 3 次磁盘操作来获取图像:一次将目录元数据读入内存,第二次将 inode 加载到内存中,第三次读取文件内容。“
我曾假设文件系统目录元数据和 inode 总是会被操作系统缓存在 RAM 中,并且文件读取通常只需要 1 个磁盘 IO。
该论文中概述的“多个磁盘 IO 读取单个文件”问题是否是 NAS 设备独有的,还是 Linux 也存在同样的问题?
我计划运行一个 Linux 服务器来提供图像。有什么方法可以最大程度地减少磁盘 IO 数量吗?最好确保操作系统将所有目录和 inode 数据缓存在 RAM 中,并且每次文件读取仅需要不超过 1 个磁盘 IO?
答案1
Linux 有同样的“问题”。这里这是我的一个学生两年前发表的一篇论文,其中展示了 Linux 上的效果。多个 IO 可以来自以下几个来源:
- 在文件路径的每个目录级别上进行目录查找。可能需要读取目录 inode 和一个或多个目录条目块
- 文件的 Inode
在正常 IO 模式下,缓存确实有效,并且 inode、目录和数据块的分配方式可以减少寻道。然而,实际上所有文件系统都共享的正常查找方法对于高度随机化的流量不利。
以下是一些想法:
1) 与文件系统相关的缓存会有所帮助。大型缓存将吸收大部分读取。但是,如果您想在一台机器中放置多个磁盘,磁盘与 RAM 的比率会限制缓存量。
2)不要使用数百万个小文件。将它们聚合为更大的文件,并将文件名和偏移量存储在文件中。
3)将元数据放置或缓存在SSD上。
4) 当然,要使用没有完全无序的磁盘目录格式的文件系统。readdir 不应花费超过线性时间,而直接文件访问理想情况下只需对数时间。
保持目录较小(少于 1000 个左右)应该不会有太大帮助,因为您需要更多需要缓存的目录。
答案2
这取决于您计划使用的文件系统。在读取文件数据系统之前:
- 读取目录文件。
- 读取文件的 inode
- 读取文件的各个部分
如果文件夹包含大量文件,这会对缓存造成很大的压力。
答案3
您可能无法将所有目录和 inode 数据保存在 RAM 中,因为您的目录和 inode 数据可能比 RAM 多。您也可能不想这样做,因为 RAM 可能更适合用于其他用途;在您的图像示例中,您是否更希望将经常访问的图像的数据缓存在 RAM 中,而不是将不经常访问的图像的目录条目缓存在 RAM 中?
话虽如此,我认为vfs_cache_压力旋钮用于控制这一点。“当 vfs_cache_pressure=0 时,内核将永远不会因内存压力而回收 dentry 和 inode,这很容易导致内存不足的情况。”