跳转到: 导航, 搜索

Swift/ideas/小文件

< Swift‎ | ideas

Swift 中的小文件优化

影响: Haystack, bluestore, git 包文件

将每个文件作为单独的文件存储的一个大问题是,这会在驱动器上创建大量的 inode。 如果你的集群中有小对象(很常见),并且有大容量驱动器(越来越常见),那么仅 XFS 分区的 inode 和目录项就可能耗尽你的 RAM。 Swift 尝试将这些内容保存在页面缓存中,但它实在太大了。 这意味着

  • 存储存在大量的 FS 元数据开销
  • 任何需要遍历每个文件的操作都 *很慢*
  • 小的纠删码对象在考虑 FS 开销时最终可能会变得相对巨大

想法

在每个后缀目录(或分区目录?)中保留两个 FS 树。 一个是“正常”的,即当前的方式。 另一个用于小文件,并使用 slab 文件和索引系统。 slab 文件是磁盘上的一个文件,它是小对象的连接数据+元数据。 索引文件通过名称或哈希以及在 slab 中的偏移量引用 slab 中的每个对象。

挑战

  • 碎片或压缩
  • 分块传输编码(在不知道 content-length 的情况下)
    • 对象服务器可以缓冲例如 1MB(或“小”的任何大小),如果它在第一次读取中,则使用 slab。 否则,使用正常的 FS 文件
  • 额外的磁盘寻道以查找 slab 或平面文件
  • 在 slab 文件中找到正确的位置
    • 仅附加到 slab 文件,并使用压缩过程来处理已删除数据的“空洞”
  • 在复制期间协调不同的 slab
  • 我们将索引文件保存在 RAM 中,还是按需读取? 如果是前者,这比 inode/dentries 更昂贵还是更便宜? 如果是后者,额外的 IO 的惩罚有多大?

意想不到的额外好处 (?)

  • 全局复制可能更快(复制一个 slab 文件而不是许多小文件)
  • 更快地引入新驱动器
  • EC 中的小文件优化

替代方案

为什么要使用 slab 分配器? 其他东西会更好吗? 也许诀窍(或有趣的部分)仅仅在于 slab 中内容的簿记(环形缓冲区、LSM 树(或 trie)、跳表等)。 实际的媒体数据所在的位置重要吗(旋转驱动器与闪存)? 我怀疑有编写内存分配器经验的人可能会提出有趣的想法。 我们应该使用一个或多个更大的文件在文件系统上吗? 为什么不直接与块设备通信? 在什么时候我们需要自己发明一个完整的文件系统,并且在这种情况下,我们与已经可用的文件系统相比有什么好处?

链接

值得阅读/查看


想进一步讨论? 在 IRC 上找到 notmyname