DeepSeek 3FS 与 JuiceFS:架构与特性比较

news2025/3/19 14:20:40

近期,DeepSeek 开源了其文件系统 Fire-Flyer File System (3FS),使得文件系统这一有着 70 多年历时的“古老”的技术,又获得了各方的关注。在 AI 业务中,企业需要处理大量的文本、图像、视频等非结构化数据,还需要应对数据量的爆炸式增长,分布式文件系统因此成为 AI 训练的关键存储技术。

本文旨在通过深入分析 3FS 的实现机制,并与 JuiceFS 进行对比,以帮助用户理解两种文件系统的区别及其适用场景。同时,我们将探讨 3FS 中的值得借鉴的创新技术点。

01 架构对比

3FS

3FS (Fire-Flyer File System) 是一款高性能的分布式文件系统,专为解决 AI 训练和推理工作负载而设计,该系统使用高性能的 NVMe 和 RDMA 网络提供共享存储层。3FS 由 DeepSeek 在 2025 年 2 月开源。
3FS 主要包括以下模块:

  • 集群管理服务(Cluster Manager)
  • 元数据服务(Metadata Service)
  • 存储服务(Storage Service)
  • 客户端 (FUSE Client、Native Client)

所有模块通过 RDMA 网络通信。元数据服务和存储服务向集群管理服务发送心跳信号。集群管理服务负责处理成员变更,并将集群配置分发给其他服务和客户端。为了提高系统的可靠性和避免单点故障,会部署多个集群管理服务,其中一个被选为主节点。当主节点发生故障时,另一个管理器会被提升为主节点。集群配置通常存储在可靠的分布式服务中,例如 ZooKeeper 或 etcd。

当进行文件元数据操作(例如打开或创建文件/目录),请求被发送到元数据服务,以实现文件系统语义。元数据服务有多个,并且是无状态的,它们不直接存储文件元数据,而是依赖支持事务的键值数据库 FoundationDB 来存储这些数据。因此,客户端可以灵活地连接到任意元数据服务。这种设计使得元数据服务可以在没有状态信息的情况下独立运作,进而增强了系统的可伸缩性和可靠性。

每个存储服务管理若干本地 SSD,并提供 chunk 存储接口。存储服务采用 CRAQ ( Chain Replication with Apportioned Queries)来确保强一致性。3FS 中存储的文件被拆分为默认 512K 大小相等的块,并在多个 SSD 上进行复制,从而提高数据的可靠性和访问速度。

3FS 客户端提供两种接入方式: FUSE Client 和 Native Client。 FUSE Client 提供常见 POSIX 接口的支持,简单易用。Native Client 提供更高的性能,但是用户需要调用客户端 API ,具有一定的侵入性,下文我们还将对此作更详尽的解析。

JuiceFS

JuiceFS 是一个云原生分布式文件系统,其数据存储在对象存储中。社区版可与多种元数据服务集成,适用场景广泛,于 2021 年在 GitHub 开源。企业版专为高性能场景设计,广泛应用于大规模 AI 任务,涵盖生成式 AI、自动驾驶、量化金融和生物科技等。
JuiceFS 文件系统包括三部分组成:

  • 元数据引擎:用于存储文件元数据,包括常规文件系统的元数据和文件数据的索引。
  • 数据存储:一般是对象存储服务,可以是公有云的对象存储也可以是私有部署的对象存储服务。
  • JuiceFS 客户端:提供 POSIX(FUSE)、Hadoop SDK、CSI Driver、S3 网关等不同的接入方式。

架构差异

从模块划分上看两个文件系统差异不大,都采用了元数据与数据分离的设计,各个模块功能也较类似。不同于 3FS 和 JuiceFS 企业版,JuiceFS 社区版兼容多种开源数据库存储元数据,对元数据的操作都封装在客户端,用户不需要再单独运维一个无状态的元数据服务。

存储模块

3FS 使用大量本地 SSD 进行数据存储,为了保证数据存储的一致性,3FS 使用 CRAQ 这一简洁的数据一致性算法 。几个副本被组成一个 Chain,写请求从 Chain 的 Head 开始,一直到达 Chain 的 Tail 时返回写成功应答。读请求可以发送到 Chain 的所有副本,如果读到脏节点的数据,该节点会联系 Tail 节点检查状态。如下图所示。

数据的写入是按顺序逐节点传递,因此会带来比较高的延时。如果 Chain 当中的某个副本不可用, 3FS 会把这个副本移到 Chain 的末尾,等副本可用的时候再做恢复。恢复的时候需要把整个 Chunk 的内容复制到这个副本,而非使用不可用期间的增量数据。如果要做到同步写所有副本和增量恢复数据,那写的逻辑会复杂非常多,比如 Ceph 使用 pg log 保证数据一致性。尽管 3FS 这种设计会导致写延迟,但是对于以读为主的 AI 应用场景,影响不大。

JuiceFS 利用对象存储作为数据存储解决方案,从而可享有对象存储带来的若干优势,如数据可靠性、一致性等。存储模块提供了一组用于对象操作的接口,包括 GET/PUT/HEAD/LIST 等,用户可以根据自己的需求对接具体的存储系统。比如不同云厂商的对象存储,也可以选择私有部署的对象存储比如 MinIO、Ceph RADOS 等系统。社区版 JuiceFS 提供本地缓存来应对 AI 场景下的带宽需求,JuiceFS 企业版使用分布式缓存满足更大的聚合读带宽的需求。

元数据模块

在 3FS 中,文件的属性以 KV 的形式存储在元数据服务中。该服务是一个无状态的高可用服务,依靠 FoundationDB 做支撑。FoundationDB 是 Apple 开源的优秀分布式 KV 数据库,具有很高的稳定性。FoundationDB 所有键值使用 Key 做全局排序,然后均匀拆分到不同的节点上。

为了优化 list 目录的效率,3FS 使用字符 “DENT” 前缀加父目录 inode 号和名字作为 dentry 的 Key。Inode 的 Key 是通过将 “INOD” 前缀与 inode ID 连接而构造的,其中 inode ID 采用小端字节序编码,以便将 inodes 分布到多个 FoundationDB 节点上。这个设计与 JuiceFS 使用的 TKV(Transactional Key-Value Database) 进行元数据服务的存储方式类似。

JuiceFS 社区版的元数据模块,与存储模块类似也提供一组操作元数据的接口,可以接入不同的元数据服务,比如 Redis,TiKV 等 KV 数据库,MySQL,PostgreSQL 等关系型数据库,也可以使用 FoundationDB。JuiceFS 企业版使用自研高性能元数据服务,可根据负载情况来平衡数据和热点操作,以避免大规模训练中元数据服务热点集中在某些节点的问题(比如因为频繁操作临近目录文件的元数据引起)。

客户端

3FS 的客户端除了提供 FUSE 操作外,还提供了一组 API 用于绕过 FUSE 直接操作数据,也就是 Native Client,接口的调用方式有点类似于 Linux AIO。这组 API 的作用是避免使用 FUSE 模块带来的数据拷贝,从而减少 I/O 延迟和对内存带宽的占用。下面将详细解析这组 API 如何实现用户进程与 FUSE 进程之间的零拷贝通信。

3FS 通过 hf3fs_iov 保存共享内存的大小,地址和其他一些属性,使用 IoRing 在两个进程间通信。

当用户调用接口,创建 hf3fs_iov 时,会在 /dev/shm 上分配内存,并创建一个指向这个共享内存的软链接,软链接的地址位于 /mount_point/3fs-virt/iovs/,这是个虚拟目录。3FS FUSE 进程收到创建软链接请求,并且发现它的地址位于上述虚拟目录后,就会根据软链接的名字解析出这块共享内存的相关参数,并将内存的地址注册到所有 RDMA 设备(除了 IORing )。ibv_reg_mr 返回的结果被存在 RDMABuf::Inner 数据结构中,用于后续发送 RDMA 请求。

同时,IORing 的内存也使用 hf3fs_iov 保存,只是在创建对应的软链接时,文件名中会有更多的 IORing 相关的信息。如果 FUSE 进程发现这个内存是用于创建 IORing,也会在它的进程内创建对应的 IORing。这样设置之后,用户进程和 FUSE 进程就可以访问相同的 IORing 了。

进程间协作方面,3FS 在 /mount_point/3fs-virt/iovs/ 目录中创建 3 个不同的虚拟文件用于共享 3 个不同优先级的提交信号量 (submit sem ),用户进程将请求放到 IORing 后使用这些信号量通知 FUSE 进程有新的请求。 IORing 尾部包含请求完成信号量,FUSE 进程通过调用 sem_post 通知用户进程 IORing 上有新的请求完成。以上整个机制确保了两个进程间的高效数据通信和操作同步。

3FS 的 FUSE 客户端实现了文件和目录的基本操作,而 JuiceFS FUSE 客户端的实现更加全面。比如,在 3FS 文件系统中文件的长度是最终一致的,这意味着在写的过程中用户可能访问到不正确的文件长度。而 JuiceFS 在每次成功上传对象后会立即更新文件长度。此外,JuiceFS 还提供了以下这些常用的高级文件系统功能:

  • 支持 BSD 锁(flock)和 POSIX 锁(fcntl)
  • 支持 file_copy_range 接口
  • 支持 readdirplus 接口
  • 支持 fallocate 接口

除了 FUSE 客户端,JuiceFS 还提供 Java SDK,S3 Gateway,CSI Driver 等接入方式。企业版还提供 Python SDK,Python SDK 将 JuiceFS 客户端在用户进程中运行,避免了通过 FUSE 导致的额外性能开销。具体见文档:Python SDK。

02 文件分布对比

3FS 文件分布

3FS 将每个文件分成固定长度的 chunk,每个 chunk 位于一个上文提到的链上( CRAQ 算法)。用户使用 3FS 提供的一个脚本,生成一个 chain table。然后将这个表提交到元数据服务。创建新文件时,系统会从表中选取特定数量的 chain (数量由 stripe 定义),并将这些 chain 的信息存入文件的元数据中。

因为 3FS 中的 chunk 是固定的,客户端只需要获取一次 inode 的 chain 信息,就可以根据文件 inode 和 I/O 请求 的 offset,length 计算出这个请求位于哪些 chunk 上,从而避免了每个 I/O 都从数据库查询的需求。可以通过 offset/chunk_size 得到 chunk 的索引。 而 chunk 所在的 chain 的索引就是 chunk_id%stripe。有了 chain 的索引就可以得到 chain 的详细信息(比如这个 chain 由哪些 target 组成)。然后,客户端根据路由信息将 I/O 请求发送到相应的存储服务。存储服务收到写请求后以 copy-on-write (COW)的方式将数据写入新的位置。原来的数据在引用数据清零前仍然是可读的。

为了应对数据不平衡问题,每个文件的第一个 chain 按照轮询( round roubin) 的方式选择。比如当 stripe 为 3 时,创建一个文件,其选择的 chain 为:chain0,chain1,chain2。那么下一个文件的 chain 为:chain1,chain2 和 chain3。系统会将选择的 3 个 chain 做随机排序,然后存储到元数据中。下图为 stripe 为 3 时一个文件的分布示例,chain 随机排序后的顺序是:1,3,2。

JuiceFS 文件分布

JuiceFS 按照 Chunk、Slice、Block 的规则进行数据块管理。每个 Chunk 的大小固定为 64M,主要用于优化数据的查找和定位。实际的文件写入操作则在 Slice 上执行,每个 Slice 代表一次连续的写入过程,属于特定的 Chunk,并且不会跨越 Chunk 的边界,因此长度不超过 64M。Chunk 和 Slice 主要是逻辑上的划分,而 Block(默认大小为 4M)则是物理存储的基本单位,用于在对象存储和磁盘缓存中实现数据的最终存储。更多细节可以参考官网介绍。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

JuiceFS 中的 Slice 是在他文件系统中不常见的一个结构。主要功能是记录文件的写入操作,并在对象存储中进行持久化。对象存储不支持原地文件修改,因此,JuiceFS 通过引入 Slice 结构允许更新文件内容,而无需重写整个文件。这与 Journal File System 有些类似,其中写入操作仅创建新对象,而不是覆盖现有对象。修改文件时,系统会创建新的 Slice,并在该 Slice 上传完毕后更新元数据,从而将文件内容指向新的 Slice。被覆盖的 Slice 内容随后通过异步压缩过程从对象存储中删除,导致在某些时刻对象存储的使用量会暂时超过文件系统实际使用量。

此外,JuiceFS 的所有 Slice 均为一次性写入,这减少了对底层对象存储一致性的依赖,并大大简化了缓存系统的复杂度,使数据一致性更易于保证。这种设计还为实现文件系统的零拷贝语义提供了便利,支持如 copy_file_range 和 clone 等操作。

03 3FS RPC (Remote Procedure Call) 框架

3FS 使用 RDMA 作为底层网络通信协议,目前 JuiceFS 尚未支持,下面对此做一些分析。

3FS 通过实现一个 RPC 框架,来完成对底层 IB 网络的操作。除了网络操作外,RPC 框架还提供序列化,小包合并等能力。因为 C++ 不具有反射能力,所以 3FS 还通过模版实现了一个反射库,用于序列化 RPC 使用的 request、response 等数据结构。需要被序列化的数据结构只需要使用特定的宏定义需要序列化的属性。RPC 调用都是异步完成的,所以序列化后的数据只能从堆上分配,等待调用完成后再释放。为了提高内存的分配和释放速度,分配对象都使用了缓存。3FS 的缓存有两部份组成,一个 TLS 队列和一个全局队列。 从 TLS 队列获取缓存时不需要加锁;当 TLS 缓存为空时就得加锁,从全局队列中获取缓存。所以在最优情况下,获取缓存是不需要加锁的。

与 I/O 请求的负载不同,缓存对象的内存都未注册到 RDMA 设备中。因此,当数据到达 IBSocket 后,会被拷贝到一个在 IB 设备注册过的缓冲区中。多个 RPC 请求可能被合并为一个 IB 请求发送到对端。下图为 FUSE Client 调用 Meta 服务的 RPC 过程。

04 特性对比

对比项3FSJuiceFS 社区版JuiceFS 企业版
元数据无状态元数据服务+FoundationDB独立数据库服务自研高性能分布式元数据引擎(可横向扩展)
数据存储自主管理使用对象存储使用对象存储
冗余保护多副本对象存储提供对象存储提供
数据缓存无缓存本地缓存自研高性能多副本分布式缓存
数据加密不支持支持支持
数据压缩不支持支持支持
配额管理不支持支持支持
网络协议RDMATCPTCP
快照不支持支持克隆支持克隆
POSIX ACL不支持支持支持
POSIX 兼容性少量子集完全兼容完全兼容
CSI 驱动没有官方支持支持支持
客户端FUSE + Native ClientPOSIX(FUSE)、Java SDK、S3 网关POSIX(FUSE)、Java SDK、S3 网关、Python SDK
多云镜像不支持不支持支持
跨云和跨区数据复制不支持不支持支持
主要维护者DeepSeekJuicedataJuicedata
开发语言C++, Rust (本地存储引擎)GoGo
开源协议MITApache License 2.0商业软件

05 总结

大规模 AI 训练中最主要的需求是高读带宽,为此 3FS 采用了性能优先的设计策略,将数据存储在高速磁盘上,并且用户需要自行管理底层数据存储。这种方法提升了性能,但成本较高,维护也更繁重。此外,为了充分发挥底层硬件的性能,其架构实现了客户端到网卡的零拷贝,利用共享内存和信号量减少 I/O 延迟和内存带宽占用。此外,通过带 TLS 的 I/O buffer pool 和合并网络请求,3FS 增强了小 I/O 和文件元数据操作的能力,并引入了性能更优的 RDMA 技术。我们将继续关注 3FS 在性能优化方面的进展,并探索如何将这些技术应用于我们的场景中。

JuiceFS 使用对象存储作为底层数据存储,用户因此可大幅降低存储成本并简化维护工作。为了满足 AI 场景的对读性能的需求,JuiceFS 企业版引入了分布式缓存、分布式元数据服务和 Python SDK,从而提高文件系统的性能和扩展能力,并同时兼顾低存储成本。在接下来发布的 v5.2 企业版中,在 TCP 网络中实现了零拷贝,进一步提升数据传输效率。

JuiceFS 提供完整的 POSIX 兼容性和成熟活跃的开源生态,适应更广泛的使用场景,并支持Kubernetes CSI,极大简化了云平台的部署和运维工作。此外,JuiceFS 还提供了 Quota、安全管理和数据灾备等多项企业级管理功能,让企业可以更便捷地在生产环境中部署和应用 JuiceFS。

希望这篇内容能够对你有一些帮助,如果有其他疑问欢迎加入 JuiceFS 社区与大家共同交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity WebGL项目访问时自动全屏

Unity WebGL项目访问时自动全屏 打开TemplateData/style.css文件 在文件最下方添加红色框内的两行代码 使用vscode或者其他编辑器打开index.html 将按钮注释掉,并且更改为默认全屏

C# WPF编程-Menu

C# WPF编程-Menu 布局:代码:效果 在WPF(Windows Presentation Foundation)中,Menu控件用于创建下拉菜单或上下文菜单,它提供了丰富的定制选项来满足不同的应用需求。下面将介绍如何在WPF应用程序中使用Menu…

Docker和containerd之概览(Overview of Docker and Containerd)

Docker和containerd之概览 容器本质上就是一个进程。 Namespace是一种逻辑分组机制,允许您将集群资源划分为独立的虚拟环境。每个 Namespace 为资源提供了一个范围,使得不同的团队、应用程序或环境可以在同一集群中共存,而不会相互干扰。 C…

【多线程】线程不安全问题

文章目录 多线程不安全的原因大的层面->多线程是随机调度的容易产生死锁 小的层面->内存不可见性引入volatile关键字 指令重排序不是原子性带来的隐患 synchronized锁的互斥性及作用可重入性——解决死锁 wait()和notify()两个突然迸发出的疑问 多线程不安全的原因 大的…

【C++】树和二叉树的实现(下)

本篇博客给大家带来的是用C语言来实现数据结构树和二叉树的实现! 🐟🐟文章专栏:数据结构 🚀🚀若有问题评论区下讨论,我会及时回答 ❤❤欢迎大家点赞、收藏、分享! 今日思想&#xff…

kafka指北

为自己总结一下kafka指北,会持续更新。创作不易,转载请注明出处。 目录 集群controller选举过程broker启动流程 主题创建副本分布ISRleader副本选举机制LEO 生产数据流程同步发送和异步发送 分区策略ack应答生产者发送消息的幂等性跨分区幂等性问题&…

7、vue3做了什么

大佬认为有何优点: 组合式api----逻辑集中、对ts有更好的支持RFC–开放了一个讨论机制,可以看到每一个api的提案,方便源码维护,功能扩展,大家一起讨论 官方rfc响应式独立,new Proxy,天生自带来…

基于大语言模型与知识图谱的智能论文生成工具开发构想

基于大语言模型与知识图谱的智能论文生成工具开发构想 一、研究背景与意义 1.1 学术写作现状分析 #mermaid-svg-FNVHG5EiEgVSCpHK {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-FNVHG5EiEgVSCpHK .error-icon{fil…

JUC大揭秘:从ConcurrentHashMap到线程池,玩转Java并发编程!

目录 JUC实现类 ConcurrentHashMap 回顾HashMap ConcurrentHashMap CopyOnWriteArrayList 回顾ArrayList CopyOnWriteArrayList: CopyOnWriteArraySet 辅助类 CountDownLatch 线程池 线程池 线程池优点 ThreadPoolExecutor 构造器各个参数含义: 线程…

4.3--入门知识扫盲,IPv4的头部报文解析,数据报分片,地址分类(包你看一遍全部记住)

IPv4协议:网络世界的快递包裹指南(附拆箱说明书) “IPv4就像一张明信片,既要写清楚地址,又要控制大小别超重” —— 某网络工程师的桌面铭牌 一、IPv4报头:快递面单的终极艺术 1.1 报头结构图(…

苍穹外卖-阿里云OSS使用

第一步: package com.sky.properties;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;Component ConfigurationProperties(prefix "sky.alioss") …

Vue生命周期_Vue生命周期钩子

一、生命周期介绍 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。 在此过程中,它也会运行被称为生命周期钩子的函数,让…

数据库设计实验(4)—— 数据更新实验

一、目的与要求 掌握用SQL语句实现数据的插入、修改和删除。 二、实验准备 1. 建立一个商店的数据库store,记录顾客及其购物情况,由下面三个表组成: 商品(商品号,商品名,单价,商品类别&#x…

Apache DolphinScheduler:一个可视化大数据工作流调度平台

Apache DolphinScheduler(海豚调度)是一个分布式易扩展的可视化工作流任务调度开源系统,适用于企业级场景,提供了一个可视化操作任务、工作流和全生命周期数据处理过程的解决方案。 Apache DolphinScheduler 旨在解决复杂的大数据…

再学:call与delegatecall、call转账 Bank合约

目录 1.call与delegatecall 2.transfer && call 3.若想内部传递abi编码 4.Bank合约 1.call与delegatecall call:切换上下文 delegatecall:不切换上下文 delegatecall可以理解为 A在调用B这个集成在A的方法 可升级合约,常用del…

关于解决新版本spring项目请求测试接口返回406的问题

目录 一、问题产生 二、问题排查 (1)首先是打断点debug进行排查 (2)网上查找相关资料排查 (3)老项目测试 三、问题解决 一、问题产生 使用Apifox对后端发送请求进行接口测试时返回状态码406&#xff0…

linux入侵排查_应急响应

1.实验目标 掌握linux系统中信息收集的方法 掌握linux系统中持久化操作方法及排查方式 掌握linux系统入侵排查思路 2.实验步骤 1.统计攻击者爆破次数 2.排查攻击者第一次使用恶意用户登录的时间 3.检查sudoer文件 4.排查计划任务 5.排查计划任务 6.排查恶意服务 7.排查…

AI视频生成产品体验分享(第2趴):Vidu、Hailuo、Runway、Pika谁更胜一筹?

hi,大家,继上次体验完可灵、即梦和pixverse,今天打算从产品经理的角度再研究下Vidu、Hailuo、Runway、Pika这几款产品!欢迎加入讨论! 一、产品简介 1. Vidu:国产自研的「一致性标杆」 📌官网…

R语言高效数据处理-自定义格式EXCEL数据输出

注:以下代码均为实际数据处理中的笔记摘录,所以很零散, 将就看吧,这一篇只是代表着我还在,所以可能用处不大,这一段时间都很煎熬! 在实际数据处理中为了提升效率,将Excel报表交付给…

基于srpingboot高校智慧校园教学管理服务平台的设计与实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…