首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >为啥 DeepSeek-3FS元数据无状态,CephFS 的 元数据 要搞得这么复杂?

为啥 DeepSeek-3FS元数据无状态,CephFS 的 元数据 要搞得这么复杂?

作者头像
早起的鸟儿有虫吃
发布于 2025-10-10 13:14:59
发布于 2025-10-10 13:14:59
5712
举报

从零开发分布式文件系统(四):一道经典面试题,深度对比 CephFS 与 3FS 的元数据架构优劣

一共8千字,让领导看绝对不看,完全不符合一页纸汇报原则

需要再次精简,

然后回到 查找/mnt/icfs/dir01/file.txt ,如何落到具体MDS节点

插播一个广告,#曙光诚聘分布式存储# 工作 地点天津找人了

需要可以内推

毛线编织, 手工, 黄色, 针织图案
毛线编织, 手工, 黄色, 针织图案

面试官提问:

看你项目经历有实现过文件系统,

请描述查找/mnt/icfs/dir01/file.txt 过程?

小青思考:(可跳过)

我不清楚部分:

•

我只是普通工程师,每天接触的安装部署,测试,然后调用接口工作,

•

根本不清楚文件磁盘io过程,之前从网络看过,不属于自己知识,自己也描述不上来,不清楚,内核更不懂

•

同事很多工作,处理大量问题,百分之一比不过,根本处理了

•

想到这里 ,我只能回答 不清楚,然后面试结束。

•

我就是我遇到最大问题,别人一句话,让自己陷入头脑的战争 可怕

我清楚部分是:(这个很重要,越具体越好,精确到每个参数)

为了测试功能,我搬运过机器,部署过机器集群

具体机型:

•

系统架构:多个节点组成一个集群,一个集群划分不同模块 支持不同协议客户端,元数据节点,数据存储节点,监控协调节点,虽然相同模块但是后台实现完全不一样

•

支持扩展到1万个节点,EB级别,必然是去中心化的设计

•

机柜:2U,4U 代表设备高度,在机架上 占用多个格子, 设备越高 放的磁盘越多,一个设备 60个,100个HDD盘

•

CPU型号:lscpu Intel® Xeon® Gold 6342 Processor 24内

•

网络接类型:至少4个网卡 ,ethtool 命令 千兆 万兆带宽,InfiniBand IB

•

网络配置:/etc/sysconfig/network-scripts/ifcfg-eth0

•

交换机,IB交换机,不是路由器

•

访问接口:通过NFS等协议,挂载文件系统

物理视图 2U
物理视图 2U

物理视图 2U

部署配置:

组件

节点类型

数量

核心配置

存储配置

数据存储节点

OSD (HDD)

60个HDD

每块硬盘直接对应1个OSD服务60个进程

数据池

元数据存储节点

OSD (NVMe)

2

2块1.8TB NVMe盘,各分4区 共创建8个OSD

元数据池

元数据服务

MDS

4

一个节点至少4-8个

Ceph Metadata Server (MDS)

客户端节点

Client

3

无需本地存储,通过网络访问Ceph集群

•

CRUSH 是 Ceph 用于数据分布的算法,它决定了如何将数据对象映射到 OSD 上。CRUSH 根据集群拓扑,去中心化的,导致扁平化存储,无目录树结果

•

Ceph Metadata Server (MDS)保证文件目录结构,多节点存储

我做过操作:

vdbench 创建文件,批量手工touch /mnt/icfs/dir01/file.txt 文件,

然后存储整个集群当中,神奇

我定位操作: 假如创建失败了,是那个服务出现问题MDS,不能每个节点,每个服务查询 太多了,清楚知道,该服务在那个节点看日志

回答重点:

•

用户态执行 cat /mnt/icfs/dir01/file.txt 命令 客户端怎么处理

•

客户端发送对应那个MDS查询文件 获取inode信息

•

客户端根据indoe信息查询文件

3. 小青回答:

文件系统是怎么通过路径来知道文件所在的磁盘位置?

回答:从客户端发起请求到 定位具体数据在那个元数据节点, 不回答 文件io具体处理过程

回答重点:

•

用户态执行 cat /mnt/icfs/dir01/file.txt 命令 客户端怎么处理

•

客户端发送对应那个MDS查询文件 获取inode信息

•

客户端根据indoe信息查询文件

3.1 客户端:文件接口怎么转变具体RPC请求

如下面三个图 无论后端是

•

hello demo服务

•

Ceph存储服务

•

3FS存储服务

对客户端来说 操作系统提供这样接口

•

FUSE:从内核到用户态的文件系统

•

用户空间实现文件系统 Filesystem in Userspace,调用自己写程序,fuse经过内核的中转站。

s3fs allows Linux, macOS, and FreeBSD to mount an S3 bucket via FUSE(Filesystem in Userspace). s3fs makes you operate files and directories in S3 bucket like a local file system,

一个用户态文件系统,挂载点为 /tmp/fuse 用户二进制程序文件为 ./hello ;

当执行 ls -l /tmp/fuse 命令的时候, 流程如下: 1. IO 请求先进内核,经 vfs 传递给内核 FUSE 文件系统模块; 2. 内核 FUSE 模块把请求发给到用户态,由 ./hello 程序接收并且处理。处理完成之后,响应原路返回

基于fuse实现一个分布式文件系统,后端存储可以其他系统
基于fuse实现一个分布式文件系统,后端存储可以其他系统

基于fuse实现一个分布式文件系统,后端存储可以其他系统

ceph
ceph

ceph

3.2 客户端发送到那个元数据节点处理

单机文件系统 一个查找多次IO操作

也是操作系统自带,数据,元数据存储一个节点上

•

客户端直接发送当前节点,

•

当前节点 从内存查询元数据,如果内存不存在 从磁盘查找

例如 /hello/file1

•

根目录 元数据 从磁盘查找1次

•

hello目录元数据 从磁盘查找1次

•

如果多级目录 查找多次

3.2 3FS怎么查找:文件操作变成kv操作

请描述查找/mnt/icfs/dir01/file.txt 过程?

3FS
3FS

3FS

•

文件系统遵循目录递归遍历方式查找,每个目录遍历存储哪些文件直接kv查询

(GFS除外,它存储大文件,海量小文件根本不采取这个方式,类似 前缀压缩路径方式存储)

•

客户端发送到任意元数据节点,为什么

3FS文件系统

•

文件元数据存储到KV中 包括 文件目录项 和数据分布

•

3FS 文件元数据 无状态的,任意节点都查询。

•

文件目录关系 通过kv命名区分,记住存储kv数据库中。

•

3FS 文件元数据 无状态的,重启很简单。

举例:类似表结构存储

来源:https://github.com/manuel71sj/deepseek-ai_3FS/blob/main/docs/design_notes.md

文件的 Inode 和 Dentry结构

键值模型映射

键格式

值内容

用途

DENT:{parent_inode}:{name}

child_inode

目录项查询

INOD:{inode}

{size, mode, blocks...}

文件属性获取

CHUNK:{inode}:{offset}

chunk_id

数据块定位

3FS 使用 FoundationDB 作为其元数据的分布式存储系统。 FoundationDB 提供键值存储接口,并支持可序列化快照隔离 (SSI) 事务。

3FS 将所有元数据以键值对的形式存储在 FoundationDB 中。

元服务采用无状态架构,允许管理员无缝升级或重启服务,无需中断,从而显著增强了可维护性。

当客户端遇到请求失败或超时时,它们可以自动故障转移到其他可用服务。

元操作利用 FoundationDB 的事务:

•

用于元数据查询的只读事务:fstat、lookup、listdir 等。

•

用于元数据更新的读写事务:创建、链接、取消链接、重命名等。

对比:典型案例 tikv的 kv存储数据 和Redis kv存储

吊打面试官03:如何设计一个内存文件系统(多级目录)

一个文件系统通过表存储

代码语言:javascript
复制
CREATETABLE categories (
  category_id INT PRIMARY KEY,
  parent_id   INTNULL,
  category_name TEXTNOTNULL,
FOREIGNKEY (parent_id) REFERENCES categories(category_id)
);

通过递归方式查询一个完整文件路径,直接去数据库查询可以了,简单方便。

这就是基本原理,请看看其他系统是不是按照这个思路设计的

3.3 ceph 无法把文件操作变成kv操作

请描述查找/mnt/icfs/dir01/file.txt 过程?

文件系统元数据不是直接存储到kv中

取舍

•

对象层:走去中心化(CRUSH),解决了“数十亿对象”的扩展性问题。

•

文件系统层:走中心化(MDS),因为文件系统操作(ls、rename、mkdir)需要全局一致的目录树,没法用纯算法算出来。客户端无法直接文件计算落在那个MDS

1

2010年:Ceph开始引入RADOS(可扩展自组织分布式对象存储)作为其核心存储技术,并发布了Ceph的第一个稳定版本。

2

2012年:Ceph在Linux内核中引入了RADOS Block Device(RBD)模块,从而支持块存储。这是Ceph变得更加多样化并用于虚拟化和云存储的重要一步。

3

2013年:Ceph的文件系统组件CephFS引入,使其成为一个全面的存储解决方案,包括对象存储、块存储和文件存储。

Ceph核心是RADOS, 根据 Ceph: A Scalable, High-Performance Distributed File System 描述

RADOS 设计目标是存储文件中的数据对象方式存储(块存储), 对象和对象直接是扁平化结构,没有没有文件系统概念(刚开始不是为文件系设计的),

代码语言:javascript
复制
Ceph OSD Daemons store data as objects in a flat namespace. 

This means that
objects are not stored in a hierarchy of directories. 

RADOS对象
RADOS对象

RADOS对象

Ceph的 文件系统元数据必须 MDS 管理,不然无法形成一棵树

特性

Ceph (CephFS)

3FS (Fire-Flyer File System)

核心设计

目录即对象

全局有序KV,前缀范围查询

存储后端

RADOS 对象存储

FoundationDB

Inode键

{Inode号}.{分片号}(如 1099511627776.00000000)

"INOD" + <Inode编号>(小端编码,如 INOD\x02\x00...)

目录项键

存储在目录对象的OMap中,Key为条目名

"DENT" + <父目录Inode编号> + <条目名>(如 DENT123dir01)

目录结构

一个目录对应一个或多个RADOS对象,通过分片管理大量条目

无独立目录对象,同一目录下所有条目因键前缀相同而自然连续

关键优势

与Ceph生态深度集成,利用RADOS的成熟特性

强一致性事务,元数据服务无状态,易于水平扩展

查找过程

1

起点:连接根目录 客户端首先会连接到一个已知的MDS。 这个MDS可能恰好是根目录 /的“权威MDS”,

2

逐级遍历路径

查找过程会沿着路径 /mnt/icfs/dir01/file.txt逐级进行:

•

接收到客户端请求的MDS(我们称为接收MDS)首先会检查第一级目录 mnt的权威MDS是谁。

•

如果 mnt目录的权威就是自己,接收MDS会直接查询本地的元数据缓存。

•

如果 mnt目录的权威是另一个MDS(比如MDS-2),接收MDS会将这部分查找请求转发给MDS-2。

•

MDS-2 作为 mnt目录的权威,会解析其下的 icfs目录项。

•

同样地,它会判断 icfs目录的权威MDS是谁。

•

这个过程会一直重复,直到找到最终文件 file.txt的inode信息。

3

返回结果

•

一旦找到 file.txt对应的inode,这个信息会沿着MDS转发链原路返回最终送达客户端。

•

客户端获得inode后,就可以直接与OSD(对象存储守护进程)交互,读写文件数据

说明:ceph MDS虽然是单线程的,减少锁交互,但是性能并不高,维护很复杂

分布式锁
分布式锁

分布式锁

mds状态
mds状态

mds状态

ceph 并没有统一结构存储 记录 元数据 与MDS分配关系。

而是每个MDS 维护各种边界。

每次重启 时候 不断与 其他MDS交互 获取完整目录树

目录导入 导出导出概念 作为事物 ,各自记录记录 各自日志 。

3.4 为什么要分片 (fragmentation)

•

目录可能非常大(比如百万文件),单个 MDS 扛不住。

•

所以 CephFS 把目录拆成多个 frag (片段),不同 frag 可以交给不同 MDS 管理。

目录内容通过目录片段进行分布,可以看到具体的获取方式

目录片段对象命名格式为{dir_ino:x}.00000000,其中dir_ino是目录的inode号。

查看名为vdb.1_1.dir(目录下有100万个文件)的目录的inode号为1099511627788,转换为16进制为1000000000C

[root@node2 cephfs]# rados -p cephfs-metadata ls

根目录的inode信息,存放在1.00000000.inode对象当中。

3.5 为什么:客户端获得inode后,就可以直接与OSD

代码语言:javascript
复制
All file data in CephFS is stored as RADOS objects. 

CephFS clients can directly
access RADOS to operate on file data.

MDS only handles metadata operations.

文件数据到对象的映射

文件数据以<inode number>.<object index>的格式存储为RADOS对象。

四、面试官反问:节点故障, 扩容如何保证一致性

4.1 3FS 甩手掌柜

•

把文件才做 变成kv操作,

•

然后保证kv操作一致性

元操作利用 FoundationDB 的事务:

•

用于元数据查询的只读事务:fstat、lookup、listdir 等。

•

用于元数据更新的读写事务:创建、链接、取消链接、重命名等。

4.2ceph 依靠MDS数据维护目录树,MDS保证事物一致性。

太复杂了,实现功能太多了,远离他

看一个看

启动过程
启动过程

启动过程

海洋, 日出, 半岛, 法国, 景观, 地平线
海洋, 日出, 半岛, 法国, 景观, 地平线

🔍 MDS与元数据管理

CephFS 为了高性能和扩展性,没有用统一的中央数据库来记录元数据与 MDS 的映射。它依赖两点机制:

•

动态子树分区:目录树被切成多个子树,每个子树只由一个 MDS 管理。MDS 会监控访问热度,负载不均时可把子树迁移给其他 MDS。

•

MDS 边界维护:每个活跃 MDS 知道自己负责的子树范围,也大致了解其他 MDS 的边界,从而避免单点瓶颈。

🔄 MDS启动与目录树重建

MDS 启动或重启时,需要与其他 MDS 协同,确定目录树分区和职责:

1

加载基础元数据:从 metadata pool 取出根目录等必要信息。

2

加入集群并同步:与 Monitors 和其他 MDS 交换信息,确认自己接管的子树,或进入 Standby 等待。

这就是为什么重启时 MDS 要不断交互,以保证弹性和高可用。

📦 目录导入导出作为事务

目录子树迁移是 分布式事务,保证一致性:

•

事务操作:目标 MDS 先写“导入中”,源 MDS 再写“导出”,最后目标写“导入完成”。

•

日志独立记录:源、目标及相关 MDS 都会写日志。这样即使故障,也能恢复到一致状态。

参考

•

https://www.ieisystem.com/global/file/2024-08-07/17230245620812c975afc90a667f436001912c4457a16533.pdf

动人的作品,为自己而写,刚刚好打动别人

1️⃣ 如果有更多疑问,联系小王,一起交流,进步

2️⃣ 关注公众号:后端开发成长指南(回复"面经"获取)获取过去我全部面试录音和面试复盘。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 面试官提问:
  • 小青思考:(可跳过)
  • 3. 小青回答:
    • 3.1 客户端:文件接口怎么转变具体RPC请求
    • 3.2 客户端发送到那个元数据节点处理
      • 单机文件系统 一个查找多次IO操作
    • 3.2 3FS怎么查找:文件操作变成kv操作
    • 3.3 ceph 无法把文件操作变成kv操作
    • 3.4 为什么要分片 (fragmentation)
      • 3.5 为什么:客户端获得inode后,就可以直接与OSD
      • 文件数据到对象的映射
    • 四、面试官反问:节点故障, 扩容如何保证一致性
    • 4.1 3FS 甩手掌柜
      • 4.2ceph 依靠MDS数据维护目录树,MDS保证事物一致性。
      • 🔍 MDS与元数据管理
      • 🔄 MDS启动与目录树重建
      • 📦 目录导入导出作为事务
    • 参考
      • 动人的作品,为自己而写,刚刚好打动别人
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档