返回

文章详情

SBD:我们在家中有一个文件系统

Hacker News2026年10月22日 13:09

作者:丹尼尔·博塔 图片由安妮·鲁伊特提供 我对那些自己做意大利面的人的看法不太友好。在这里,我只想用他们作为如何不思考基础设施建设的例子。相信在某件事情上投入的努力越多,结果就越好,这种想法很不公平。但基础设施的核心是制作一袋1美元的意大利面:一种简单而有效的东西(而且不需要你花一个星期的时间刮去厨房角落的面粉)。当Sprits的工作开始时,这是一种新类型的基础设施,适用于新类型的产品。因此,当我们在意大利面区找不到合适的文件系统时,我们自己制作了一个。这很聪明,但这正是我们不喜欢它的原因。本文介绍了其替代品,Sprites块设备(SBD)。它是你从货架上抓取的一袋意大利面,你唯一会注意到的区别是更好的可靠性。 它始终是对象存储 我们对Sprites存储的一个核心观点自v1以来没有改变:一个Sprite的磁盘的根本是对象存储,而不是Sprite所运行的任何服务器上的NVMe。这使得一个Sprite能够睡眠,在不同的服务器上唤醒,并仍然能够在离开的地方找到它的文件。一个Sprite的耐久状态或多或少是一个桶中的位置。我们详细而富有感情地写过这个原因。关于对象存储有一点:它们无法更改对象的某一部分。要更改一个字节,你必须替换整个对象。这对于Linux程序来说是一个不好的文化契合,因为它们常常在文件中间重写几个字节。必须有一些东西来处理这种转换。在启动时,那样的东西是经过重度修改的JuiceFS。JuiceFS的标准形式将存储分为数据(桶中的数据块)和元数据(说明哪些数据块构成哪些文件的地图),存储在数据库中。然而,我们并没有这样使用它。我们修改后的版本使用重写的SQLite元数据后端,并通过Litestream保持耐久性。它只存储一个文件:一个100 GB的磁盘映像,挂载在一个loop设备上,里面是ext4。Linux进行所有普通的ext4操作。JuiceFS只保存映像。它运行得很好。Sprites在其上发布,人们制造了大量的它们,而检查点非常快,因为检查点基本上只是重新排列元数据。然而,随着使用量的增加,裂缝开始显现。 说谎的清单 带有元数据库的文件系统有两个不可分离的组件:桶中的数据块和解释这些数据块如何组合在一起的数据库。当它们一致时,你就有文件。当它们不一致时,你就麻烦了。我们在上面建立的每一层都必须继承这种安排并加以补充。JuiceFS下的检查点是磁盘映像的写时复制克隆,因此元数据库跟踪每个检查点以及活动磁盘的数据块。另一个SQLite数据库checkpoints.db列出了检查点本身,以及每个检查点要挂载到loop设备上的哪个映像文件。因此,一个Sprite的磁盘是数据块,加上一个元数据库,说明哪些数据块组成了每个映像,加上一个检查点数据库,说明哪个映像是哪一个。每个部分都是单独保持耐久的,因此每个部分可以是正确的,而其他部分可以是错误的。有什么可能出错的呢? 一个可能基于生活经验的故事:有一天,一个Sprite停止启动。JuiceFS在请求对象存储中的一个数据块时得到了404。我们希望快速,因此在写回模式下运行JuiceFS。它首先在元数据中记录一个数据块,然后再上传字节。如果在这两个步骤之间的任何时间机器被关闭,元数据将指向一个不存在的数据块。因此,顶层的ext4文件系统会找到一个未通过校验和的目录块并变为只读。将Sprite移动到新机器上并不会帮忙,恢复检查点也不会,因为JuiceFS的检查点是克隆。它们共享相同的块,因此每个检查点都会有相同的缺口。 我代理吃了我的食物 更重要的不是这些问题的技术细节,而是它们胆怯的本性带来了Fly.io历史上最强烈的自食其果的时期。如果你打算让计算机为代理进行自食其果,那么代理必须是吃掉这些食物的。因此我们构建了一个装置,不断驱动一队Sprites进行写、检查点、睡眠、唤醒和恢复,反复验证每个返回的字节。我们将其指向400个JuiceFS Sprites,进行了约5000个周期。其中一些永久失去了检查点的能力。 好吧……见鬼。在一段时间内,我们继续审问我们的配方。进行更多调和,更多修复工具,以及越来越聪明的方法来保持三个分类账的一致性。但带有修复工具包的意大利面无论怎么做都会留下奇怪的味道。 只是一个磁盘 引入:Sprites块设备(SBD)。它将一个桶呈现给Linux内核作为一个块设备,通过NBD进行连接。Sprite将该设备格式化为ext4并挂载,这与挂载任何磁盘的方式一样。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

☕请我喝杯咖啡