写点什么

DeepSeek 3FS 实测|从设计哲学到 AI 场景适配法则

作者:焱融科技
  • 2025-03-14
    北京
  • 本文字数:6486 字

    阅读完需:约 21 分钟

AI 技术的演进正深刻重塑经济社会与人类文明进程,每一次技术突破与创新都极具探讨价值。焱融认为,DeepSeek 3FS 给业界提供了高性能存储在设计和实现思路上的工程借鉴。3FS 为适配 DeepSeek 业务,做了很多取舍,本质上是针对 DeepSeek 这种特定应用下的定制存储方案。此次,焱融存储技术团队提供了更多 3FS 核心测试数值,为行业全面评估 3FS 提供了参考。


自 DeepSeek 于去年下半年发布《Fire-Flyer AI-HPC: A Cost-Effective Software-Hardware Co-Design for Deep Learning》【1】论文以来,焱融存储技术团队即启动对 3FS 文件系统的专项研究。研究聚焦于 DeepSeek 算力集群与存储集群的组网架构,重点解析 3FS 在网络拥塞规避机制与高带宽读取性能上的实现路径。在 3FS 开源后,团队通过实际测试验证其技术特性:测试数据表明, 3FS 非常重视读带宽的优化,而放松对写性能、元数据性能的要求,可以看出 3FS 是专为 DeepSeek 而生,旨在满足其特定的性能需求。


我们由衷感叹 3FS 开源给业界带来的震撼,以及它所提供的宝贵参考价值。在今天,尽管 DeepSeek 3FS 可能已经不再是“热点”,但其在技术上的创新与在工程实现上的高超技巧,仍具备持续研究与借鉴价值。本文旨在通过工程实践视角,系统赏析 3FS 的设计哲学,结合实测数据,为行业构建更立体的技术评估框架提供依据。

3FS 架构分析


从整体架构来看,分布式文件系统并无太多意外之处,3FS 也不例外。其主要由 Client、集群管理(mgmtd)、元数据服务(Meta Service, mds)以及数据服务(Storage Service)这四大部分构成。



比较特别的是,3FS 的元数据服务(mds)使用分布式 kv 数据库 FoundationDB。因此,mds 的实现相对简单,元数据的分布式一致性交给 FoundationDB 负责即可。然而,有得必有失。整个文件系统支持的文件规模和 mds 的性能均受限于 FoundationDB。后面元数据操作的实测数据验证了这一点。这再次证明,在存储的世界里,任何设计都难以兼顾所有期望,取舍在所难免。


在数据部分,3FS 使用了 CRAQ 算法,在 Chain Replication 算法基础上大幅优化了读性能。但从算法特点可知写延时会比较高,维护数据多版本的代价也较大,写的性能,尤其是随机写的性能将大打折扣。这又是 3FS 在设计和优化上的一次决策和取舍。



3FS Client 分为 fuse client 和 native client 两种。fuse client 更为通用,但性能受限于 fuse 框架。native client 则分为两部分,其中元数据操作仍然通过 fuse 处理,数据部分通过称为 USRBIO 的 lib 库,经由用户态 fuse daemon,通过 zero-copy 的方式读写 3FS storage。这样既通过 fuse 规避了元数据操作的复杂性,又规避了 fuse 数据读写的性能缺陷。



  • 若用户的业务选择采用 fuse client,则需要承受 fuse 带来的性能缺陷。相关详情可参考 FAST 2017 论文《To FUSE or Not to FUSE: Performance of User-Space File Systems》【2】。


  • 若选择使用 native client,则需要借助 USRBIO 库对业务代码进行修改,这并非易事。即便使用了 USRBIO 库,元数据仍然需要通过 FUSE 进行处理,因此仍会承受 fuse 带来的性能影响。关于如何利用 USRBIO 访问文件,我们已根据官方示例做了简单注释。


#include <hf3fs_usrbio.h>
constexpr uint64_t NUM_IOS = 1024;constexpr uint64_t BLOCK_SIZE = (32 << 20);
int main() { // io request 结构,通过共享内存 IoRing 将命令发给 fuse daemon struct hf3fs_ior ior; hf3fs_iorcreate4(&ior, "/hf3fs/mount/point", NUM_IOS, true, 0, 0, -1, 0); // io request 数据描述结构,通过 IoRing 和 fuse daemon 进行 zero-copy 方式的读写 struct hf3fs_iov iov; hf3fs_iovcreate(&iov, "/hf3fs/mount/point", NUM_IOS * BLOCK_SIZE, 0, -1);
// 通过 fuse client 打开文件,获取到文件数据位置等信息 int fd = open("/hf3fs/mount/point/example.bin", O_RDONLY); // 将 fd 关联的文件元数据放到全局表中,供后续 IO 查询 hf3fs_reg_fd(fd, 0);
// 准备发起 1024 次 read,将要读的位置信息,存放数据的内存地址准备好,根据 fd 查询文件数据位置 for (int i = 0; i < NUM_IOS; i++) { hf3fs_prep_io(&ior, &iov, true, iov.base + i * BLOCK_SIZE, fd, i * BLOCK_SIZE, BLOCK_SIZE, nullptr); } // 发起 read hf3fs_submit_ios(&ior);
// 收割 read 结果 hf3fs_cqe cqes[NUM_IOS]; hf3fs_wait_for_ios(&ior, cqes, NUM_IOS, NUM_IOS, nullptr);
// 释放资源 hf3fs_dereg_fd(fd); close(fd); hf3fs_iovdestroy(&iov); hf3fs_iordestroy(&ior);
return 0;}
复制代码


实测结果及解析


理论分析需结合实践验证。为此,我们准备了一套全闪测试环境,从数据性能、元数据性能等方面测试 3FS 的表现。测试环境如下:



元数据性能经 mdtest 测试,在同等条件下(为排除数据性能影响,未触发数据 IO),测试所得性能如以下表格所示。测试结果清晰显示,3FS 元数据操作性能不佳,这与前文架构分析的预期相符。



数据性能通过 fio 进行测试,其中 native client 测试采用官方提供的 fio_usrbio。带宽测试使用顺序大 IO,IOPS 测试使用 4K 随机 IO。



除性能外,我们还对 3FS 的 POSIX 兼容性及其在集群故障时的表现进行了关注与测试。


  • 在 POSIX 兼容性测试中,我们采用 pjdfstest 对 3FS fuse client 进行验证。测试结果显示,3FS 有 3400+测试用例未能通过。这一结果并不出乎意料,因为 3FS 的设计并未注重对 POSIX 的高度兼容。


  • 对于 3FS 在集群故障下的表现,我们进行了以下测试:在终止一个 storage 进程时,业务会出现 10 秒的卡顿;在重新启动该 storage 进程时,同样会出现 10 秒的业务卡顿。此外,当主动使 storage 进程所在的服务器 panic 时,业务在长时间卡顿后会报错。这一结果略显意外,推测 DeepSeek 的业务团队对此应有相应的适配和优化措施。



3FS 的选择 | 专为 DeepSeek 而生


无论是从架构、代码分析,还是从实际测试结果抑或 3FS 的设计文档来看,都可以清晰地发现,3FS 在技术设计和工程实现上果断选择了“重读轻写”的做法,可谓专为 DeepSeek 而生。在硬件架构上,3FS 仅支持“RDMA+全闪”模式,而不支持 TCP。这充分体现了其明确的设计目标——DeepSeek 需要“RDMA+全闪”这种高性能存储系统,那么 3FS 就只做“RDMA+全闪”。


但即便 3FS 主要追求读带宽,其实现也远非想象得那么简单。


从 3FS 早在 2019 发布的官方博客文章,就可以看出 3FS 已经在思考和解决一些关键问题。例如,从《3FS 优化 01 | 服务端优化》【3】和《3FS 优化 02 | 客户端内存使用优化》【4】可以看出,3FS 通过全链路 Direct IO 和在用户侧实现 zero-copy 的方式,减少内存拷贝,规避内存带宽限制,以充分发挥 RDMA 网络的超高吞吐能力。


  • 关于全链路 Direct IO,在 FAST 2024 的论文《Combining Buffered I/O and Direct I/O in Distributed File Systems》【5】及 FAST 2025 的论文《Rethinking the Request-to-IO Transformation Process of File Systems for Full Utilization of High-Bandwidth SSDs》【6】中均有相关讨论,面对 NVMe SSD 等高性能设备,传统的 Page Cache 反而阻碍了性能的发挥。焱融在《CPU 使用率飙升,Buffer IO 引发的性能问题》【7】一文中对此也有对应的讨论和优化。


  • 关于用户侧 zero-copy,业务通过 USRBIO 将用户数据关联到 RDMA 内存,然后通过 RDMA 单边操作,直接读写后端存储。从官方博客来看,3FS 早在 2019 年便开始进行了这一方案的研究,充分体现了 3FS 的技术创新和突破能力。


此外,在“RDMA+全闪”模式下,RDMA 网络拥塞控制是拦路虎之一。DeepSeek 也曾面临相同的问题,其在《Fire-Flyer AI-HPC: A Cost-Effective Software-Hardware Co-Design for Deep Learning》【1】论文中详细阐述了这一问题,并提及了 3FS 在 RDMA 拥塞控制方面的解决方案。


The storage network has a Fat-Tree topology that provides full bisection bandwidth. By design, each 3FS client can access every storage service. At peak load, incast congestion is observed on the client side. To mitigate this congestion, a request-to-send control mechanism is implemented in storage service and client. After receiving a read request from a client, the service reads data from SSD and asks the client’s permission to transfer the data. The client limits the number of concurrent senders. When a storage service is granted permission to transfer, it sends the data with a RDMA WRITE followed by a RDMA SEND to notify the client. The request-to-send control increases end-to-end IO latency but it’s required to achieve sustainable high throughput.


3FS server 在响应 client 读取时,首先回向 client 发起数据发送请求,client 侧具有流控机制,待流控条件满足后,client 再给 server 颁发数据传输许可,之后 server 通过 RDMA WRITE 将数据写到 client 对应内存位置。整个流程被称为 request-to-send 机制。


3FS 的代码实现正是基于论文中提出的这一思路,虽然这样会增加读的延时,但它可以有效控制网络拥塞,并能够持续、充分地利用高性能存储网络的带宽。这里可再次看出 3FS 对读带宽的重视性,及其技术创新突破能力。关于 request-to-send 机制,简要代码分析如下:


// (1) [client side] fuse client启动Result<Void> hf3fs::fuse::FuseClients::init(const flat::AppInfo &appInfo, ...) {  // std::shared_ptr<storage::client::StorageClient> storageClient;  storageClient = storage::client::StorageClient::create(clientId, fuseConfig.storage(), *mgmtdClient);}
// (2)[client side] StorageClient::createstd::shared_ptr<StorageClient> h3fs::storage::client::StorageClient::create(ClientId clientId, ...) { std::shared_ptr<StorageClient> client; client = std::make_shared<StorageClientImpl>(clientId, config, mgmtdClient); client->start();}
// (3) [client side] StorageClientImpl::startResult<Void> hf3fs::storage::client::StorageClientImpl::start() { // StorageMessenger messenger_.start("StorageMgr");}
// (4) [client side] StorageMessenger::startResult<Void> hf3fs::storage::client::StorageMessenger::start(const std::string &name = "StorageMsgr") { // hf3fs::net::Client client_; return client_.start(name);}
// (5) [client side] net::Client::startResult<Void> hf3fs::net::Client::start(const std::string &name = "Cli") { RETURN_AND_LOG_ON_ERROR(processor_.start(name)); RETURN_AND_LOG_ON_ERROR(serdeServices_.addService(std::make_unique<RDMAControlImpl>(config_.rdma_control()), true)); return ioWorker_.start(name);}// src/common/net/RDMAControl.h, 注册了RDMATransmissionReq的处理函数SERDE_SERVICE(RDMAControl, 10) { SERDE_SERVICE_METHOD(apply, 1, RDMATransmissionReq, RDMATransmissionRsp); };
// (6) [client side] RDMAControlImpl默认配置下,同时只支持64个并发传输class RDMAControlImpl : public serde::ServiceWrapper<RDMAControlImpl, RDMAControl> { class Config : public ConfigBase<Config> { CONFIG_HOT_UPDATED_ITEM(max_concurrent_transmission, 64u); }; RDMAControlImpl(const Config &config) : config_(config), limiter_(std::make_shared<RDMATransmissionLimiter>(config_.max_concurrent_transmission())), guard_(config_.addCallbackGuard( [&] { limiter_->updateMaxConcurrentTransmission(config_.max_concurrent_transmission()); })) {} ...}
// (7) [server side] src/storage/service/StorageOperator.cc, 响应client的读请求// 在返回数据前,先向client申请数据传输许可CoTryTask<BatchReadReq> hf3fs::storage::StorageOperator::batchRead(ServiceRequestContext &requestCtx, const BatchReadReq &req, serde::CallContext &ctx) { if (ctx.packet().controlRDMA() && RDMATransmissionReqTimeout != 0_ms && !applyTransmissionBeforeGettingSemaphore) { co_await writeBatch.applyTransmission(RDMATransmissionReqTimeout); // 向client发起RDMA数据传输请求 }}
// (8) [server side] 给client发传输许可请求CoTask<void> CallContext::RDMATransmission::applyTransmission(Duration timeout) { net::RDMATransmissionReq req{ctx_.packet().uuid}; auto applyResult = co_await net::RDMAControl<>::apply(clientCtx, req, &options);}
// (9) [client side] client端,前面第(5)步注册的rpc服务,处理RDMATransmissionReq CoTryTask<RDMATransmissionRsp> RDMAControlImpl::apply(serde::CallContext &ctx, const RDMATransmissionReq &req) { co_await limiter_->co_wait(); // 如果并发请求太多,会在这里等待 auto prepareLatency = Waiter::instance().setTransmissionLimiterPtr(req.uuid, limiter_, startTime); if (UNLIKELY(!prepareLatency)) { limiter_->signal(0_ms); } else { transmissionPrepareLatency.addSample(*prepareLatency); } co_return RDMATransmissionRsp{}; // 返回rsp给后端,表示可以传输数据了}
// (10) [server side] src/storage/service/StorageOperator.cc, 拿到了client的传输许可后,通过rdma write给client传输数据CoTryTask<BatchReadReq> hf3fs::storage::StorageOperator::batchRead(ServiceRequestContext &requestCtx, const BatchReadReq &req, serde::CallContext &ctx) { auto postResult = FAULT_INJECTION_POINT(requestCtx.debugFlags.injectServerError(), makeError(RPCCode::kRDMAPostFailed), (co_await writeBatch.post())); // post()里传输数据}
复制代码


写在最后


从 3FS 的设计文档、架构和代码分析、再到实际测试结果,3FS 可谓专为 DeepSeek 而生。3FS 选择了重视读带宽,接受其他方面的不足,比如,较差的随机写性能、较差的元数据性能和较差的 POSIX 语义兼容性。这种取舍策略值得称赞,彰显了 3FS 团队目标明确和果断决策,他们坚持第一性原则,将满足 DeepSeek 业务需求置于首位。


在技术设计和实现层面,3FS 亦有不少亮点。例如,全链路 Direct IO、用户态 USRBIO 结合 RDMA 单边操作、以及 request-to-send 网络拥塞避免机制等。这无不体现了 3FS 团队在关键技术难点上的创新突破能力。


向 3FS 团队致敬!


参考文献


[1] Fire-Flyer AI-HPC: A Cost-Effective Software-Hardware Co-Design for Deep Learning: https://arxiv.org/abs/2408.14158

[2] To FUSE or Not to FUSE: Performance of User-Space File Systems: https://www.usenix.org/system/files/conference/fast17/fast17-vangoor.pdf

[3] 3FS 优化 01 | 服务端优化:https://www.high-flyer.cn/blog/3fs-1/

[4] 3FS 优化 02 | 客户端内存使用优化:https://www.high-flyer.cn/blog/3fs-2/

[5] Combining Buffered I/O and Direct I/O in Distributed File Systems: https://www.usenix.org/conference/fast24/presentation/qian

[6] Rethinking the Request-to-IO Transformation Process of File Systems for Full Utilization of High-Bandwidth SSDs: https://www.usenix.org/conference/fast25/presentation/zhan

[7] CPU 使用率飙升,Buffer IO 引发的性能问题:https://mp.weixin.qq.com/s/QF-g43Kp9V3D9QZr7CQQLw


了解更多请联系焱融科技公众号

用户头像

焱融科技

关注

软件定义的混合云统一文件存储 2020-05-29 加入

焱融科技是一家以软件定义存储技术为核心竞争力的高新技术企业,基于软件定义的混合云统一文件存储为企业客户提供高效存储、数据管理和应用服务,打造面向云+AI 时代的高性能存储。

评论

发布
暂无评论
DeepSeek 3FS 实测|从设计哲学到 AI 场景适配法则_文件系统_焱融科技_InfoQ写作社区