Skip to main content

在大规模AI模型训练场景中,存储系统往往是制约训练效率的关键瓶颈。数千块GPU并发读取训练数据集、高频写入检查点(Checkpoint)以及推理阶段的KVCache管理,对底层存储的吞吐带宽、随机I/O性能和并发访问能力提出了极高要求。2025年初,DeepSeek正式开源了内部使用的高性能并行文件系统3FSFire-Flyer File System),凭借其在180个存储节点上实现6.6 TiB/s聚合读吞吐的优异表现,迅速引发了业界广泛关注。

本文将全面深入地介绍3FS的技术方案、架构设计、组件功能、安装配置与运维实践,为在AI训练基础设施中考虑引入3FS的技术团队提供系统性参考。

3FS概述

什么是3FS

3FSFire-Flyer File System)是DeepSeek研发并开源的一套高性能分布式文件系统,专为AI训练和推理工作负载设计。它充分利用现代NVMe SSD的高吞吐特性与RDMA网络(InfiniBandRoCE)的低延迟、高带宽优势,为计算节点提供一个统一的共享存储层,使分布式应用能够以接近本地磁盘的速度访问存储资源。

3FS20252月以MIT许可证开源,代码托管在 github.com/deepseek-ai/3FS,目前已累计获得10k+星标。

核心特性

特性分类特性名称说明
性能与易用性存算分离架构将数千块SSD的吞吐与数百个存储节点的网络带宽聚合,客户端以无感知方式访问
性能与易用性强一致性保障基于CRAQ协议实现写全读任意,充分释放SSDRDMA带宽,保证强一致性
性能与易用性标准文件接口元数据服务基于事务型KV存储(FoundationDB),提供标准POSIX文件接口
多样化工作负载数据准备将数据分析流水线的输出组织为层级目录结构,高效管理海量中间文件
多样化工作负载数据加载支持跨计算节点随机访问训练样本,无需预取或数据集shuffle
多样化工作负载检查点保存支持大规模训练任务的高吞吐并行Checkpoint写入
多样化工作负载KVCache推理提供比DRAM更大容量、极具成本竞争力的KVCache存储方案

性能基准

以下数据均来自DeepSeek官方README中的公开实测数据:

峰值读吞吐测试:在180个存储节点(每节点配备2×200Gbps InfiniBand NIC1614TiB NVMe SSD)组成的集群上,使用500+个客户端节点(每客户端1×200Gbps InfiniBand NIC)进行压力读测试,在训练任务背景流量下最终聚合读吞吐约达6.6 TiB/s

GraySort基准:在25个存储节点(每节点2×400Gbps NIC)和50个计算节点上,对110.5 TiB的数据跨8192个分区完成排序,总耗时30分钟14秒,平均吞吐3.66 TiB/minsmallpond项目验证)。

KVCache推理:在1×400Gbps NIC的节点上,KVCache客户端峰值读吞吐最高可达40 GiB/s

架构设计

整体架构

3FS采用存算分离的分布式架构,系统由四个核心组件构成:集群管理器mgmtd)、元数据服务meta)、存储服务storage)和客户端client)。所有组件通过RDMA网络(InfiniBandRoCE)互联。

数据读写路径

客户端open文件时从元数据服务获取chunk分布信息,此后数据I/O直接与存储节点通信,无需再经过元数据服务。写请求发至链头并沿链传播,由链尾提交后反向回传ACK;读请求可发至链中任意节点,实现读负载均衡。

核心组件详解

集群管理器(mgmtd)

mgmtdManagement Daemon)是集群的控制中枢,通过心跳机制检测节点故障(租约模型:服务无法联系mgmtd超过阈值时主动退出以防脑裂)、维护和广播链表(Chain Table)变更、统一管理所有服务的配置文件,并通过选举支持高可用部署。

存储目标的公开状态如下,mgmtd据此驱动链状态转换:

公开状态可读可写说明
serving正常服务
syncing数据恢复中
waiting等待恢复启动
lastsrv已下线,曾是链中最后一个正常节点
offline已下线或介质故障

元数据服务(meta)

元数据服务负责实现文件系统语义,处理所有文件元数据操作,如opencreatemkdirrenameunlinkstat等。

无状态设计:元数据服务本身是无状态的,所有文件元数据持久化存储在FoundationDB中。这一设计带来了极高的可维护性——管理员可以在不中断服务的情况下滚动升级或重启元数据节点;客户端请求失败时可以自动故障转移到其他元数据节点。多实例部署时,请求被均匀分发到所有元数据服务实例。

元数据存储模型

文件系统元数据通过两类核心数据结构存储在FoundationDB中:

结构类型键(Key)格式值(Value)内容
Inode(文件节点)"INOD" + inode_id(小端序)权限、时间戳;文件额外存:长度、chunk大小、链表范围、随机种子;目录额外存:父目录inode_id、默认布局配置
Directory Entry(目录项)"DENT" + 父inode_id + 文件名目标inode_id + inode类型

同一目录下的所有目录项在FoundationDB中构成连续的键范围,支持高效的范围查询(listdir)。元数据操作通过FoundationDBSSISerializable Snapshot Isolation)事务保证一致性,并发冲突由FoundationDB自动检测,冲突时元数据服务自动重试事务。

文件数据布局:新建文件时,元数据服务从指定链表(Chain Table)中按轮询策略选取连续的复制链,并生成随机种子对链顺序进行shuffle,以确保数据均匀分布。客户端open文件后,可在本地独立计算出每个chunk所在的链和chunk ID,元数据服务无需参与数据I/O关键路径。

文件长度最终一致性:对于正在写入的文件,inode中记录的文件长度可能略落后于实际写入位置;客户端每隔5秒向元数据服务上报最大写入位置;close/fsync时,元数据服务通过查询存储服务获取最精确的文件长度。

存储服务(storage)

存储服务管理本地NVMe SSD,以chunk为粒度存储数据,是集群吞吐的直接来源。

数据组织:每块SSD上创建若干存储目标(Target),目标按顺序构成复制链(Chain),若干链聚合为链表(Chain Table)供元数据服务分配。不同工作负载可使用不同链表实现存储隔离。3FS通过数学优化(不完全均衡区组设计,Balanced Incomplete Block Design)构造链表,使节点故障时的读流量均匀分散,避免热点。

CRAQ复制3FS实现带分配查询的链式复制(CRAQ)保证强一致性。写请求发至链头,链头通过RDMA Read拉取数据后沿链传播,由链尾提交并反向回传ACK,同一chunk的并发写在链头串行化;读请求可发至链中任意节点(写全读任意),充分利用所有副本带宽。存储目标同时持有已提交版本(v)和待提交版本(v+1),读到待提交版本时客户端可重试或发起宽松读。

Chunk引擎与数据恢复:每块SSD由数据文件(物理块64KiB~64MiB,按2的幂次分11种规格)和RocksDB(存储chunk元数据)构成。写操作采用写时复制(CoW)语义,追加写支持原地扩展,物理块以位图管理并优先复用。节点故障恢复时,前驱节点对比元数据差异后通过full-chunk-replace增量同步,恢复与正常服务并行进行。

客户端

FUSE客户端hf3fs_fuse_main)将3FS挂载为本地文件系统,无需修改应用代码,适合大多数数据分析类工作负载。性能限制:内核态/用户态数据拷贝增加延迟;共享队列自旋锁在高并发下竞争严重(实测上限约400K IOPS4KiB随机读);Linux 5.x不支持对同一文件并发写入。

原生客户端USRBIOUser-space Ring Buffer I/O)在FUSE守护进程内实现异步零拷贝I/O,设计借鉴Linux io_uringIov为用户进程与客户端共享的大块内存(零拷贝传输区域),Ior为共享环形缓冲区(请求入队/出队)。应用通过标准open()获取fd并注册到原生API,即可绕过FUSE内核路径发起高性能异步I/O,文件元数据操作仍走POSIX接口保持兼容。

典型使用场景

AI模型训练数据加载

在大规模分布式训练中,数千个GPU并发访问共享数据集,对存储系统的随机读IOPS要求极高。

传统方案的痛点:对象存储(如S3)虽有高可扩展性,但不支持原子性目录操作(如rename、递归删除);传统NFS存在单点瓶颈;而3FS提供了真正的并行文件接口——所有计算节点共享同一命名空间,可随机访问任意训练样本,无需预先shuffle或预取,极大简化了数据加载器(DataLoader)的实现。

使用场景典型配置建议:

  • 文件数据组织建议使用层级目录结构,避免单目录文件数量过大
  • 对于随机小文件读,推荐使用USRBIO原生API以规避FUSE的锁竞争瓶颈
  • 可利用符号链接和硬链接为动态更新的数据集创建轻量快照

Checkpoint并行保存与恢复

模型训练中Checkpoint的写入是一个对存储带宽要求极高的并行写场景:数百个训练节点同时写入数十到数百GB的模型参数。

3FS的优势:

  • 多存储节点的SSD带宽聚合,Checkpoint写入速度随存储节点数量线性扩展
  • CRAQ的写全策略确保Checkpoint数据的强一致性,避免训练恢复时读到部分写入的脏数据
  • 文件系统接口与PyTorch等框架的Checkpoint保存逻辑天然兼容

KVCache推理加速

KVCacheLLM推理中用于缓存DecoderKey/Value向量的技术,传统上依赖DRAM实现,容量受限且成本高昂。将KVCache卸载到3FS后:

  • 3FS提供比DRAM更大的存储容量(NVMe SSDTB级容量对比DRAMGB级容量)
  • 通过RDMA直接访问,读延迟远低于传统网络存储
  • 实测单节点读吞吐可达40 GiB/s1×400Gbps NIC

数据分析与数据准备

3FS为数据分析流水线(如数据清洗、格式转换、特征工程)提供高性能的中间结果存储:

  • 支持原子性rename:数据处理完成后将临时目录原子地移动到最终路径,避免下游任务读到部分完成的中间结果
  • 高效的递归删除:无需逐文件删除,元数据服务直接在事务中批量处理目录删除
  • smallpond项目(DeepSeek开源的分布式数据处理框架)已原生集成3FS作为存储后端

环境要求与依赖

硬件要求

组件推荐配置
存储节点SSDNVMe SSD,推荐14TiB+,每节点8~16
网络RDMA网络:InfiniBand(推荐HDR/HDR100)或RoCE100Gbps+
存储节点内存512GB+(需要缓冲大量chunk元数据)
元数据节点内存128GB+
操作系统Ubuntu 20.04/22.04openEuler 2403sp1OpenCloudOS 9TencentOS 4

RDMA网络配置

  1. RDMA NIC分配IP地址(每个节点支持多块InfiniBandRoCE NIC
  2. 使用ib_write_bw工具验证节点间的RDMA连通性

第三方依赖

依赖版本要求用途
FoundationDB7.1+文件系统元数据存储
ClickHouse最新稳定版监控指标存储
libfuse3.16.1+FUSE客户端内核接口
Rust工具链1.75.0+(推荐1.85.0+部分Rust绑定代码编译

FoundationDB注意事项FoundationDB客户端版本必须与服务端版本一致,或手动将对应版本的libfdb_c.so复制到目标节点。集群文件fdb.cluster通常位于/etc/foundationdb/fdb.cluster

系统依赖安装

Ubuntu 20.04

apt install cmake libuv1-dev liblz4-dev liblzma-dev libdouble-conversion-dev \
libdwarf-dev libunwind-dev libaio-dev libgflags-dev libgoogle-glog-dev \
libgtest-dev libgmock-dev clang-format-14 clang-14 clang-tidy-14 lld-14 \
libgoogle-perftools-dev google-perftools libssl-dev libclang-rt-14-dev \
gcc-10 g++-10 libboost1.71-all-dev build-essential

Ubuntu 22.04

apt install cmake libuv1-dev liblz4-dev liblzma-dev libdouble-conversion-dev \
libdwarf-dev libunwind-dev libaio-dev libgflags-dev libgoogle-glog-dev \
libgtest-dev libgmock-dev clang-format-14 clang-14 clang-tidy-14 lld-14 \
libgoogle-perftools-dev google-perftools libssl-dev gcc-12 g++-12 \
libboost-all-dev build-essential

openEuler 2403sp1

yum install cmake libuv-devel lz4-devel xz-devel double-conversion-devel \
libdwarf-devel libunwind-devel libaio-devel gflags-devel glog-devel \
gtest-devel gmock-devel clang-tools-extra clang lld \
gperftools-devel gperftools openssl-devel gcc gcc-c++ boost-devel

安装与部署

本节以官方Setup Guide中的六节点集群(1个元数据节点 + 5个存储节点)为示例,集群IDstage

节点规划示例

节点角色操作系统示例IP内存存储网络
meta(元数据/管理节点)Ubuntu 22.04192.168.1.1128GB-RoCE
storage1Ubuntu 22.04192.168.1.2512GB14TB×16RoCE
storage2Ubuntu 22.04192.168.1.3512GB14TB×16RoCE
storage3Ubuntu 22.04192.168.1.4512GB14TB×16RoCE
storage4Ubuntu 22.04192.168.1.5512GB14TB×16RoCE
storage5Ubuntu 22.04192.168.1.6512GB14TB×16RoCE

步骤一:获取源码并编译

# 克隆仓库并初始化子模块
git clone https://github.com/deepseek-ai/3fs
cd 3fs
git submodule update --init --recursive
./patches/apply.sh

# 编译(以 Ubuntu 22.04 + clang-14 为例)
# <method> 根据实际情况选择 'g++10' 或 'g++11'(需全集群统一)
cmake -S . -B build \
-DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_C_COMPILER=clang-14 \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DSHUFFLE_METHOD=<method>
cmake --build build -j 32

重要-DSHUFFLE_METHOD参数必须在整个集群范围内保持一致,且一旦集群投入使用后不可更改,否则会因std::shuffle算法差异导致数据无法正确定位。新集群可任选g++10g++11;存量集群沿用原编译版本对应的method

也可使用官方提供的Docker构建镜像(适合TencentOS 4OpenCloudOS 9):

# TencentOS 4
docker pull docker.io/tencentos/tencentos4-deepseek3fs-build:latest

# OpenCloudOS 9
docker pull docker.io/opencloudos/opencloudos9-deepseek3fs-build:latest

步骤二:初始化监控服务

meta节点上初始化ClickHouse表并启动监控收集器服务:

# 创建 ClickHouse 监控表
clickhouse-client -n < ~/3fs/deploy/sql/3fs-monitor.sql

# 安装监控服务
mkdir -p /opt/3fs/{bin,etc} /var/log/3fs
cp ~/3fs/build/bin/monitor_collector_main /opt/3fs/bin
cp ~/3fs/configs/monitor_collector_main.toml /opt/3fs/etc

编辑/opt/3fs/etc/monitor_collector_main.toml,配置ClickHouse连接:

[server.monitor_collector.reporter]
type = 'clickhouse'

[server.monitor_collector.reporter.clickhouse]
db = '3fs'
host = '<CH_HOST>'
passwd = '<CH_PASSWD>'
port = '<CH_PORT>'
user = '<CH_USER>'

启动监控服务:

cp ~/3fs/deploy/systemd/monitor_collector_main.service /usr/lib/systemd/system
systemctl start monitor_collector_main

步骤三:部署管理工具(admin_cli)

在所有节点上安装admin_cli

mkdir -p /opt/3fs/{bin,etc}
rsync -avz meta:~/3fs/build/bin/admin_cli /opt/3fs/bin
rsync -avz meta:~/3fs/configs/admin_cli.toml /opt/3fs/etc
rsync -avz meta:/etc/foundationdb/fdb.cluster /opt/3fs/etc

编辑/opt/3fs/etc/admin_cli.toml

cluster_id = "stage"

[fdb]
clusterFile = '/opt/3fs/etc/fdb.cluster'

查看admin_cli完整帮助文档:

/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml help

步骤四:部署集群管理服务(mgmtd)

meta节点上安装mgmtd

cp ~/3fs/build/bin/mgmtd_main /opt/3fs/bin
cp ~/3fs/configs/{mgmtd_main.toml,mgmtd_main_launcher.toml,mgmtd_main_app.toml} /opt/3fs/etc

配置mgmtd_main_app.toml(设置节点ID):

node_id = 1

配置mgmtd_main_launcher.toml(设置集群IDFoundationDB集群文件):

cluster_id = "stage"

[fdb]
clusterFile = '/opt/3fs/etc/fdb.cluster'

配置mgmtd_main.toml(设置监控服务地址):

[common.monitor.reporters.monitor_collector]
remote_ip = "192.168.1.1:10000"

初始化集群并启动mgmtd

# 初始化集群(链表ID=1,chunk大小=1MB,条带大小=16)
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
"init-cluster --mgmtd /opt/3fs/etc/mgmtd_main.toml 1 1048576 16"

# 启动 mgmtd 服务
cp ~/3fs/deploy/systemd/mgmtd_main.service /usr/lib/systemd/system
systemctl start mgmtd_main

# 验证集群初始化
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"list-nodes"

init-cluster参数说明:第一个数字为链表ID,第二个为chunk大小(字节),第三个为文件条带大小(即一个文件在链表中使用的连续链数量)。可运行help init-cluster查看完整参数文档。

步骤五:部署元数据服务(meta)

meta节点上安装元数据服务:

cp ~/3fs/build/bin/meta_main /opt/3fs/bin
cp ~/3fs/configs/{meta_main_launcher.toml,meta_main.toml,meta_main_app.toml} /opt/3fs/etc

配置meta_main_app.toml

node_id = 100

配置meta_main_launcher.toml

cluster_id = "stage"

[mgmtd_client]
mgmtd_server_addresses = ["RDMA://192.168.1.1:8000"]

配置meta_main.toml

[server.mgmtd_client]
mgmtd_server_addresses = ["RDMA://192.168.1.1:8000"]

[common.monitor.reporters.monitor_collector]
remote_ip = "192.168.1.1:10000"

[server.fdb]
clusterFile = '/opt/3fs/etc/fdb.cluster'

上传配置到mgmtd并启动元数据服务:

# 上传元数据服务配置到 mgmtd
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"set-config --type META --file /opt/3fs/etc/meta_main.toml"

# 启动元数据服务
cp ~/3fs/deploy/systemd/meta_main.service /usr/lib/systemd/system
systemctl start meta_main

# 验证元数据服务已加入集群
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"list-nodes"

步骤六:部署存储服务(storage)

在每个存储节点上执行以下操作(以storage1节点为例):

# 格式化 NVMe SSD 为 XFS 并挂载
mkdir -p /storage/data{1..16}
mkdir -p /var/log/3fs
for i in {1..16}; do
mkfs.xfs -L data${i} -s size=4096 /dev/nvme${i}n1
mount -o noatime,nodiratime -L data${i} /storage/data${i}
done
mkdir -p /storage/data{1..16}/3fs

# 增大异步 aio 请求上限
sysctl -w fs.aio-max-nr=67108864

meta节点同步二进制文件和配置:

rsync -avz meta:~/3fs/build/bin/storage_main /opt/3fs/bin
rsync -avz meta:~/3fs/configs/{storage_main_launcher.toml,storage_main.toml,storage_main_app.toml} /opt/3fs/etc

配置storage_main_app.toml(每个存储节点使用不同的node_id,范围10001~10005):

node_id = 10001

配置storage_main_launcher.toml

cluster_id = "stage"

[mgmtd_client]
mgmtd_server_addresses = ["RDMA://192.168.1.1:8000"]

配置storage_main.toml(添加所有SSD数据目录):

[server.mgmtd]
mgmtd_server_addresses = ["RDMA://192.168.1.1:8000"]

[common.monitor.reporters.monitor_collector]
remote_ip = "192.168.1.1:10000"

[server.targets]
target_paths = [
"/storage/data1/3fs", "/storage/data2/3fs", "/storage/data3/3fs",
"/storage/data4/3fs", "/storage/data5/3fs", "/storage/data6/3fs",
"/storage/data7/3fs", "/storage/data8/3fs", "/storage/data9/3fs",
"/storage/data10/3fs", "/storage/data11/3fs", "/storage/data12/3fs",
"/storage/data13/3fs", "/storage/data14/3fs", "/storage/data15/3fs",
"/storage/data16/3fs",
]

上传配置并启动存储服务:

# 上传存储服务配置到 mgmtd
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"set-config --type STORAGE --file /opt/3fs/etc/storage_main.toml"

# 启动存储服务
rsync -avz meta:~/3fs/deploy/systemd/storage_main.service /usr/lib/systemd/system
systemctl start storage_main

# 验证存储节点已加入集群
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"list-nodes"

步骤七:创建用户、存储目标与链表

# 创建管理员用户(token 会打印到控制台,需保存)
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"user-add --root --admin 0 root"
# 将 token 保存到文件
echo "<PRINTED_TOKEN>" > /opt/3fs/etc/token.txt

# 使用数据放置优化脚本生成链表配置
pip install -r ~/3fs/deploy/data_placement/requirements.txt

# 求解最优数据放置方案(5节点、3副本、每块SSD至少6个存储目标)
python ~/3fs/deploy/data_placement/src/model/data_placement.py \
-ql -relax -type CR \
--num_nodes 5 --replication_factor 3 --min_targets_per_disk 6

# 生成链表和存储目标配置命令
python ~/3fs/deploy/data_placement/src/setup/gen_chain_table.py \
--chain_table_type CR --node_id_begin 10001 --node_id_end 10005 \
--num_disks_per_node 16 --num_targets_per_disk 6 \
--target_id_prefix 1 --chain_id_prefix 9 \
--incidence_matrix_path \
output/DataPlacementModel-v_5-b_10-r_6-k_3-λ_2-lb_1-ub_1/incidence_matrix.pickle

# 创建存储目标
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
< output/create_target_cmd.txt

# 上传链配置
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"upload-chains output/generated_chains.csv"

# 上传链表配置
/opt/3fs/bin/admin_cli --cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"upload-chain-table --desc stage 1 output/generated_chain_table.csv"

# 验证链和链表
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"list-chains"
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"list-chain-tables"

步骤八:挂载FUSE客户端

# 安装 FUSE 客户端
cp ~/3fs/build/bin/hf3fs_fuse_main /opt/3fs/bin
cp ~/3fs/configs/{hf3fs_fuse_main_launcher.toml,hf3fs_fuse_main.toml,hf3fs_fuse_main_app.toml} \
/opt/3fs/etc

# 创建挂载点
mkdir -p /3fs/stage

# 配置 hf3fs_fuse_main_launcher.toml

编辑/opt/3fs/etc/hf3fs_fuse_main_launcher.toml

cluster_id = "stage"
mountpoint = '/3fs/stage'
token_file = '/opt/3fs/etc/token.txt'

[mgmtd_client]
mgmtd_server_addresses = ["RDMA://192.168.1.1:8000"]

上传配置并启动FUSE客户端:

# 上传 FUSE 客户端配置到 mgmtd
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"set-config --type FUSE --file /opt/3fs/etc/hf3fs_fuse_main.toml"

# 启动 FUSE 客户端
cp ~/3fs/deploy/systemd/hf3fs_fuse_main.service /usr/lib/systemd/system
systemctl start hf3fs_fuse_main

# 验证挂载
mount | grep '/3fs/stage'

挂载成功后,即可像使用本地文件系统一样访问3FS

ls /3fs/stage
df -h /3fs/stage

常用命令参考

集群状态查询

ADMIN_CLI="/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml"
MGMTD='--config.mgmtd_client.mgmtd_server_addresses ["RDMA://192.168.1.1:8000"]'

# 查看所有节点状态
$ADMIN_CLI $MGMTD "list-nodes"

# 查看所有复制链
$ADMIN_CLI $MGMTD "list-chains"

# 查看所有链表
$ADMIN_CLI $MGMTD "list-chain-tables"

# 查看帮助文档
$ADMIN_CLI $MGMTD "help"
$ADMIN_CLI $MGMTD "help <command>"

配置管理

# 查看当前集群配置
$ADMIN_CLI $MGMTD "get-config --type META"
$ADMIN_CLI $MGMTD "get-config --type STORAGE"
$ADMIN_CLI $MGMTD "get-config --type FUSE"

# 更新配置(修改 *_main.toml 后必须重新上传)
$ADMIN_CLI $MGMTD "set-config --type META --file /opt/3fs/etc/meta_main.toml"
$ADMIN_CLI $MGMTD "set-config --type STORAGE --file /opt/3fs/etc/storage_main.toml"
$ADMIN_CLI $MGMTD "set-config --type FUSE --file /opt/3fs/etc/hf3fs_fuse_main.toml"

用户管理

# 创建普通用户
$ADMIN_CLI $MGMTD \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"user-add 1001 username"

# 创建管理员用户
$ADMIN_CLI $MGMTD \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"user-add --admin 1002 adminuser"

存储目标与链管理

# 查看存储目标详情
$ADMIN_CLI $MGMTD \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"list-targets"

# 上传链配置(用于扩容或替换故障节点后重建链)
$ADMIN_CLI $MGMTD \
--config.user_info.token $(<"/opt/3fs/etc/token.txt") \
"upload-chains new_chains.csv"

服务日志查询

# 查看 mgmtd 服务日志
journalctl -u mgmtd_main -f

# 查看 meta 服务日志
journalctl -u meta_main -f

# 查看 storage 服务日志
journalctl -u storage_main -f

# 查看 FUSE 客户端日志
journalctl -u hf3fs_fuse_main -f

# 查看各服务的文件日志
ls /var/log/3fs/

性能基准测试

3FS提供了基于USRBIO接口的fio引擎用于性能测试:

# 使用 fio USRBIO 引擎进行读测试(需安装并配置 fio 的 3FS 插件)
# 详见 benchmarks/fio_usrbio/README.md
fio --ioengine=usrbio \
--filename=/3fs/stage/test_file \
--rw=randread \
--bs=1m \
--iodepth=32 \
--numjobs=8 \
--runtime=60 \
--time_based \
--name=3fs_read_test

优缺点分析

优势

优势说明
超高聚合吞吐带宽随存储节点数量线性扩展,实测180节点达6.6 TiB/s读吞吐
强一致性CRAQ协议保证写全读任意,无需应用层处理脏读或版本冲突
零拷贝I/OUSRBIO原生API通过共享内存和RDMA实现真正零拷贝,适合性能敏感工作负载
无状态元数据服务元数据服务可滚动升级、横向扩展,无单点瓶颈
标准文件接口POSIX兼容,无需改造现有训练框架和数据处理代码
故障容忍链式复制支持多副本容错,故障转移自动完成;链表设计优化了故障时的流量均衡
开源免费MIT许可证,完整开放源码,社区活跃

劣势与局限

局限说明
基础设施要求高依赖RDMA网络(InfiniBandRoCE)和高质量NVMe SSD,硬件投入较大
部署运维复杂需要独立部署FoundationDBClickHouse等第三方组件,部署链路较长
仅支持Linux目前仅支持Linux平台,且测试覆盖的发行版有限
FUSE性能上限对于小随机读场景,FUSE接口存在性能瓶颈;使用USRBIO原生API需修改应用代码
生产运维经验积累中项目2025年初开源,社区生产部署案例相对Lustre等成熟系统仍较少
单集群规模限制元数据存储依赖FoundationDB的规模上限,超大规模集群(数千节点以上)的元数据性能需进一步验证

常见问题与解决方案

admin_cli init-cluster报错

现象:运行init-cluster命令后,mgmtd服务启动失败或命令返回错误。

原因:最常见的原因是mgmtd_main.toml配置文件存在错误(如FoundationDB集群文件路径错误、监控服务地址格式错误等)。

解决方案

  1. 检查mgmtd_main.toml中的所有配置项,尤其是FoundationDB连接配置
  2. 如果已经执行过init-cluster并产生了错误的集群配置,需要清除FoundationDB中的3FS数据后重新初始化:
# 使用 fdbcli 清除 3FS 在 FoundationDB 中的数据(谨慎操作)
fdbcli --exec "clearrange \x00 \xFF"
# 重新初始化集群
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
"init-cluster --mgmtd /opt/3fs/etc/mgmtd_main.toml 1 1048576 16"

如何构建单节点测试集群

说明3FS要求至少两个存储服务实例才能构建副本链(gen_chain_table.py使用--num-nodes=1时会失败)。

解决方案:在单机测试环境中,可在同一台机器上启动多个storage_main进程(分配不同的node_id和不同的SSD数据目录),模拟多节点部署。这仅适用于功能测试,不代表生产性能。

配置文件更新后不生效

现象:修改了*_main.toml配置文件,但服务行为未变化。

原因3FS所有服务的配置文件由mgmtd统一管理,本地文件修改后需要通过admin_cli set-config命令重新上传到mgmtd,服务在下次重启或热重载时才会使用新配置。

解决方案

# 上传更新后的配置
/opt/3fs/bin/admin_cli -cfg /opt/3fs/etc/admin_cli.toml \
--config.mgmtd_client.mgmtd_server_addresses '["RDMA://192.168.1.1:8000"]' \
"set-config --type <SERVICE_TYPE> --file /opt/3fs/etc/<config_file>.toml"

# 重启对应服务使新配置生效
systemctl restart <service_name>

部署问题通用排查方法

当部署过程中遇到任何错误时,按以下步骤逐步排查:

  1. 查看systemd日志
journalctl -u <service_name> -n 100 --no-pager
  1. 查看服务文件日志(启动服务前务必确认/var/log/3fs/目录已存在):
ls -la /var/log/3fs/
tail -f /var/log/3fs/*.log
  1. 验证RDMA连通性
# 在两个节点间测试 RDMA 带宽
ib_write_bw -d <rdma_device> <peer_ip>
  1. 验证FoundationDB连通性
fdbcli --cluster-file /opt/3fs/etc/fdb.cluster --exec "status"
  1. 检查admin_cli list-nodes输出,确认各节点状态是否符合预期

存储节点故障后集群吞吐下降

现象:某个存储节点故障后,集群整体读吞吐显著下降。

原因:链中某个节点下线后,原本发往该节点的读请求被重定向到链中其他节点,若链表设计不佳(一个节点只与少数其他节点共享链),可能导致少数节点成为热点。

解决方案

  1. 使用3FS提供的data_placement.py数学优化脚本生成链表,该脚本基于不完全均衡区组设计,确保故障节点的读流量均匀分散到最多的其他节点
  2. 故障存储节点修复后(替换SSD或重启服务),数据恢复过程自动进行,恢复完成后节点状态重回serving,集群吞吐自动恢复

FUSE客户端小文件随机读性能不足

现象:数据加载场景下,大量小文件(几KB~几十KB)的随机读IOPS无法满足训练要求。

根因Linux FUSE的多线程共享队列在高并发下存在严重锁竞争,实测上限约400K IOPS4KiB),无法充分利用RDMANVMe SSD的能力。

解决方案

  1. 对于性能敏感的数据加载工作负载,迁移到USRBIO原生API,绕过FUSE内核路径实现真正的异步零拷贝I/O
  2. 如果无法修改应用代码,可以在应用层对训练样本进行预打包(如将多个小文件合并为较大的chunk文件),减少随机小I/O次数
  3. 参考benchmarks/fio_usrbio/README.md中的fio USRBIO引擎使用说明进行性能测试与对比验证

参考资料