DeepSeek 分布式文件系统 (DFS) 简介
DeepSeek 分布式文件系统 (DFS) 简介
创建于 2025 年 4 月 15 日 2025 · 3FS · blog 3FS
系列文章
什么是 3FS?
3FS(Fire-Flyer File System,真拗口!)是 DeepSeek 在其开源周期间发布的一个分布式文件系统。 本文将深入探讨什么是分布式文件系统,以及 3FS 如何运作,首先介绍一些背景知识。
什么是分布式文件系统?
分布式文件系统会欺骗应用程序,让它们以为自己在与常规的本地文件系统交互。 这种抽象非常强大:一个实际被分散在 10 台不同机器上的文件,看起来就像一个简单的文件路径,比如 /3fs/stage/notes.txt
。
使用分布式文件系统与本地文件系统并无不同
在上图中,我通过运行 mkdir
和 cat
命令,在本地文件系统和分布式文件系统上创建了相同的文件夹和文件。命令完全相同。使用分布式文件系统,所有这些细节都对用户进行了抽象,用户可以简单地使用这些文件,而无需担心背后涉及多少机器、网络调用或磁盘。
为什么要使用分布式文件系统?
与本地存储相比,分布式文件系统提供了两个主要优势——它们可以服务于海量数据(高达 PB 级别),并提供超过单台机器能力的高吞吐量。 它们提供容错能力(如果一台机器宕机,系统仍然可以继续运行)和冗余(如果一个节点上的数据损坏,其他节点拥有原始副本)。
分布式文件系统被用于许多实际应用中:
- 并行处理框架(HDFS 支持 Spark)
- 具有 Dataloaders and checkpointing 的 ML 训练管道
- 由 Google’s Colossus 支持的内部大规模代码/数据存储库
- Traveling 等行业应用
- 照片存储由 Meta’s Haystack 提供支持
深入了解 3FS
那么,3FS 是如何工作的呢?
3FS 的核心由四种主要节点类型组成:
3FS 涉及的组件
这些组件具有不同的用途:
- Meta – 管理元数据:文件位置、属性、路径等。
- Mgmtd – 管理服务器控制集群配置:其他节点在哪里,哪些节点是活动的,以及复制因子。
- 可以把它想象成一个路由器,它知道每个节点的地址,可以帮助节点找到彼此。一个类似的例子是 NAT hole punching 中使用的集中式服务器。
- Storage – 节点将实际文件数据保存在物理磁盘上。
- Client – 与所有其他节点通信以查看和修改文件系统:
- 请求 Mgmtd 发现其他节点
- 请求 Meta 服务器执行文件操作(打开、状态、关闭、符号链接)
- 与存储节点传输数据
现在让我们更详细地了解每个组件。
Mgmtd
Mgmtd 注册
Mgmtd 跟踪集群中正在运行的节点。 存储和 Meta 节点在启动时注册,并定期发送心跳信号以确认它们仍然处于活动状态。 这提供了系统的中心视图——可以立即识别哪些节点已关闭。
Mgmtd 请求
节点不需要与网络中的每个其他节点保持连接。 相反,它们可以通过查询 Mgmtd 节点来发现节点。 虽然这在定位节点时增加了一个额外的往返,但它可以降低复杂性,因为节点发现不是静态的。
Mgmtd 链
此外,Mgmtd 维护在分布式算法中运行的不同节点的配置。 特别是,复制链 (CRAQ CRAQ 是一种非常棒的算法,它通过将节点视为一个链来实现强大的具有容错能力的一致性。 我将在另一节中详细解释这一点。)被建立,并且它的节点作为配置存储在 Mgmtd 中。
Meta
Meta 概述
Meta 节点比 Mgmtd 稍微复杂一些。 客户端通过 RPC 调用与它通信。 Meta 服务器在元数据存储上执行典型的文件系统操作(打开、创建、stat、取消链接)。 文件元数据驻留在 inodes 中,存储大小、权限、所有者和时间戳等属性。 DirEntry 对象将路径映射到 inodes,单个文件可能有多个 DirEntry (类似于符号链接)。 inodes 和 DirEntry 都存储在 FoundationDB 中。有人可能想知道 FoundationDB 的键是什么样的? Inode: “INOD + inode id, dir entry: “DENT” + nodeid + path,使用事务进行幂等操作。 会话管理器跟踪打开的文件,并将文件会话存储在 FoundationDB 中。 如果客户端在不关闭文件的情况下断开连接,会话管理器将启动文件同步。 文件删除请求排队到垃圾收集器,垃圾收集器在删除目录条目和 inodes 之前从存储节点删除数据。
Storage
Storage 概述
存储节点的主要功能是通过将数据分成块来管理物理存储上的数据:
- The Rust ChunkEngine。 为什么是 Rust? 好吧,有一个用 C++ 编写的遗留块管理器,名为
ChunkStore
。 我真的不明白为什么在 Rust 中,可能是因为它很有趣,并且提供了更多的安全保证。 它跟踪磁盘存储块。- Chunks 代表一块物理磁盘,并跟踪其元数据(id、大小、磁盘上的偏移量、物理磁盘、校验和、版本,……)。 这是所有其他结构用来跟踪数据块的最原始的数据结构。
- Chunk engine 不允许用户直接与 Chunks 交互,因为它会增加使用引擎的复杂性。 该引擎的界面具有操作,这些操作为用户提供了一种严格而清晰的与引擎交互的方式(查找、分配、提交、元数据……)。
- 默认情况下,所有这些都存储在 LevelDB 中,前缀字节代表操作类型(查询元数据),块 id 作为键。
- 有不同的 workers 使用 Chunk engine 来维护物理存储。
- AllocateWorker 在 Chunk engine 中分配新的 Chunks。
- PunchHoleWorker 在不再使用 Chunks 时回收它们。
- AioReadWorker 处理对 Chunks 的读取请求,并将读取请求排队到 io_uring 队列中,提交并等待完成。最初,我很惊讶。 Chunk engine 不对实际物理磁盘执行操作,它实际上只管理元数据。 这样做的原因之一可能是通过仅尝试管理元数据来保持 ChunkEngine 实现相当精简。
- 存储节点需要知道如何将写入转发到 CRAQ 链中的下一个目标。 现在,只需知道需要将写入转发到其他节点即可。
- Targets 由 Chunks 组成(可以将其视为包含不同 Chunks 的逻辑存储)。
- 链由多个 Targets 组成(通常跨越多个节点)。
- 存储节点查询 Mgmtd 服务器以获取其他节点的链以及写入需要转发到的该链中相应的 Targets(节点)。
CRAQ
CRAQ(Chain Replication with Apportioned Queries)是一种通过线性化实现强一致性的协议。 它是保持数据块具有容错能力的核心机制。 我将解释 CRAQ 的工作原理,然后展示它在 3FS 中的实现。
Craq 写入传播
写入从 head 开始。 在我们的示例中,我们将 name=henry
写入系统。 随着写入沿链向下移动,每个条目都标有版本号,并标记为“dirty”。 Dirty 的条目是不安全的,不能读取。 一旦写入到达 tail,它就会被提交并标记为“clean”。
Craq 写入提交
随着提交消息从 tail 向 head 反向传播,写入变为 clean。 每个节点提交该条目并将其标记为 clean。
Craq clean 读取
对于读取,该过程很简单:如果一个对象是 clean 的,它会立即返回给客户端。
Craq dirty 读取
挑战在于 Dirty 对象。 每个链都跟踪 Dirty 和 Clean 版本。 由于 tail 始终包含最新的已提交数据,因此副本会查询 tail 以获取最新的已提交对象,从而确保了强大的连贯性。
CRAQ 性能
CRAQ 的读取和写入性能因工作负载而异。 写入吞吐量和延迟受到链中最慢节点的限制,因为写入必须依次通过每个节点进行处理。 例如,在 zipfian 工作负载(其中频繁访问的数据占主导地位)中,读取性能会受到影响,因为对象可能为 Dirty,从而强制查询 tail 节点。 这会造成瓶颈,因为 tail 必须服务于大多数读取请求。
CRAQ 在 3FS 中是如何使用的
Storage 被条带化,CRAQ 在其之上运行
在此示例中,5 个节点,每个节点有 5 个 SSD,构成集群。 存储 Targets 复制到 3 个节点,旨在避免重叠,从而使节点故障不会显着影响整体吞吐量。 考虑一种极端情况,其中所有链都放置在节点 1、2、3 上。如果节点 1 发生故障,分布式系统将损失 1/3 的总吞吐量,而不是上图中显示的 1/5 的总吞吐量。 3FS 设计说明 显示了一个包含更深入解释的示例。 CRAQ 在其之上运行,管理 head、middle 和 tail 节点。
3FS 默认为强一致性读取。 写入从 head 流向 tail 再返回,吞吐量受到最慢节点的限制,延迟由所有链节点的组合延迟决定。
比较不同复制协议的表(图片来源:Ionia 论文中的表 1)
如比较表所示,在常见情况下,与其他协议和系统相比,CRAQ 以高写入延迟为代价,提供可扩展的低延迟读取。
其他分布式文件系统
有人可能会问——这种架构与其他分布式文件系统有何不同? 在较高层面上,这些组件是熟悉的——客户端、元数据、存储和管理节点的某些概念几乎出现在每个分布式系统中。
区别在于其现实世界的适用性和实际实施:
- 它擅长处理哪些工作负载
- 它的调整灵活性
- 部署简单性
- 吞吐量扩展能力
- 在 SLO 中保持延迟
- 可靠性
以及其更精细的技术细节决定了其可用性:
- 存在哪些瓶颈
- 它如何管理瓶颈
- 其锁定方法(或缺少锁定)
- 采用的特定数据结构
- 该软件设计的硬件
- 使用什么容错算法或纠删码
本博客系列的其余部分
考虑到这一点,我想深入分析这种相对较新的开源分布式文件系统的性能。 分布式文件系统很少出现,需要数年才能开发出来。 目前的基准测试相当有限。 没有与单节点系统和其他分布式文件系统的比较,因此很难衡量 3FS 的性能如何。
我想探索的一些问题:
- DeepSeek 的某些说法是否成立,尤其是在 FUSE 瓶颈 方面?
- 我可以以某种方式重现他们的性能图吗?
- 在什么情况下性能会下降?
- 系统的瓶颈是什么(CPU/内存/磁盘/网络)?
- 该文件系统擅长处理哪些类型的工作负载?
- 它与其他分布式文件系统相比如何?
- 它如何解决现有系统面临的问题?
- 我是否能够对系统进行任何改进?
在本系列的其余部分中,我将经历提出初步假设、测试它们并从差异中学习的过程,以更深入地了解 3FS 的实际执行方式。
更多阅读
实施细节记录在设计说明中。
提供有关早期实施阶段的其他技术文档(中文):
系统架构部分记录在 Fire-Flyer AI-HPC 论文中。
鸣谢
感谢 Vimarsh Sathia 审阅这篇文章。
喜欢阅读这篇文章?
以下是您接下来可能喜欢阅读的更多文章:
- DeepSeek 分布式文件系统 (DFS) 简介
- 为了好玩,以艰难而乏味的方式抓取 League of Legends 数据
- 为了好玩,以艰难而乏味的方式抓取 League of Legends 数据
- 独特性
- Paul Graham - 何时做你喜欢做的事
© 版权所有 2025 Henry Zhu。 # 由 Jekyll 提供支持,采用 al-folio 主题。 # 由 GitHub Pages 托管。 上次更新时间:2025 年 4 月 16 日。