头图

背景

CFS 是百度智能云文件存储,是一个大规模分布式文件系统。EuroSys'23 CFS论文主要介绍了该系统的元数据核心设计,对长期困扰文件系统元数据领域的Posix兼容性和高扩展性(特别是写扩展性)难以兼顾的问题进行了解答。

为了帮助读者更了解该系统的创新过程,百度存储团队发表了一篇文章《如何将千亿文件放进一个文件系统,EuroSys'23 CFS 论文背后的故事》,从文件系统的概念和需要解决的关键问题说起,非常详细地介绍了设计理念、演进过程。

我们在阅读论文和文章解析的过程中受益匪浅,CFS 跟 Curve 文件系统在设计上有一些理念是相同的,也有很多地方值得 Curve 借鉴、学习。本文的目的是从 CFS 的设计理念出发,对 Curve 做一次回顾,查漏补缺。

关键点解析

元数据服务的架构

//元数据服务的第三阶段:分离式架构,文中提到:分离式架构同样没有解决写扩展性的问题,写延时的表现甚至比耦合式架构更差:
- 事务在架构里的实质作用其实也是一种分布式锁,并没有解决其它分布式锁机制的缺陷,当一个写操作需要多节点参与时,无论是吞吐还是延时的表现都会比较差。
- 分离式架构处理请求时,需要先经过元数据代理层,再到数据库层,比耦合式架构的处理路径要更⻓,因此天然在性能上,特别是延时指标上更具劣势。读请求可以通过客户端直接读数据库层的方法来进行优化,但写请求就没有办法这么处理了。

这一点,之前我们有测试过使用 TiKV 作为元数据引擎,对比 Curve 文件系统原生的引擎,同样发现,使用分布式 KV 在标准测试 mdtest 下的性能并不好,是 Curve 文件系统原生引擎性能的一半。文章在[2.5 对分布式锁性能影响的定量分析中]提到,在没有锁冲突的情况下,锁在整个操作中的耗时占比也达到了 50%+。

NameSpace1.0

namespace1.0其中的一个设计要点是将文件的属性从元数据服务中剥离出来,和文件数据一起放到数据服务器中进行处理。
基于这一理念,元数据的结构如下图所示:

image.png

元数据操作需要用到的数据库的能力可以概括为:按照 secondary key 查找指定项,按照 parent\_id list,子项和 parent\_id 的事务操作。Curve 文件系统, 所有信息可以认为都是存储在分布式 KV 上(Curve 文件系统使用 Raft+Rocksdb 作为元数据)的持久化引擎,虽然没有使用数据库作为引擎,但 Curve 文件系统通过一定的放置策略加速上述提到的几个能力,以提高元数据性能:每个数据分片负责一定范围的 inodeid, 所有的 dentry 存放在 parent\_inodeid 所在的分片上。

下面我们来对比下 CFS 和 Curve 文件系统在 lookup 和 readdir 两个读操作:

  • lookup /A/B
  • Namespace1.0 查找路径:先在中查找 [rootinodeid + filenameA] 的项,获取/A的inodeid;再使用 [/A的inodeid + filenameB] 获取 /A/B 的inode。涉及到两次查表操作。
  • Curve 文件系统查找路径:先通过 [rootinodeid + filenameA] 去 rootinodeid 所在的分片上,获取/A的 dentry,解析出 inodeid;再使用[/A的inodeid + filenameB]去 /A所在的 inode 上获取 /A/B的 dentry,解析出对应的 inodeid。同样也是涉及两次 rpc 操作。
  • readdir /A
  • 在 Namespace1.0 中查找路径:先查找 [rootinodeid + filenameA] 的项,获取 /A的 inodeid,再通过 db 操作,list parentid 为 /A的 inodeid 的所有项。需要经过 db 两次查询操作。
  • Curve 文件系统查找路径:通过 [rootinodeid + filenameA] 去 rootinodeid 所在的分片上,获取/A的 dentry,解析出 inodeid;再去[/A的inodeid]所在的分片获取 parentid 为/A的 inodeid 的所有项。同样涉及到两次 rpc 操作。

关于写操作,对比 mknode 和 rename 两个写操作:

  • mknode
  • Namespace1.0 的操作路径:在 filestore 中写入文件属性的相关信息;将文件的 dentry 信息{parent\_id, name, ...} 插入 TafDB 并修改 parentid的 关联信息,这一步通过 TafDB 的分布式事务能力完成。涉及到两次 rpc 操作。
  • Curve 文件系统操作路径:选择一个分片写入文件属性相关信息;将文件 的dentry 信息插入到 parent\_id 所在的分片中,并修改 parent\_id 的 nlink 等属性信息,这一步通过本地的 RocksDB 的事务接口完成。涉及两次 rpc 操作。
  • rename
  • Namespace1.0 可以直接通过 TafDB 的分布式事务接口完成。
  • Curve 文件系统,由于 rename 涉及到删除源文件的 dentry, 在新的 parent\_id 下创建新的 dentry,涉及到多个不同分片上的操作,为此设计了额外的事务处理逻辑。

Namspace2.0

最大的一个优化点在于将分布式锁去除,使用原子变量的操作来替代。能实现这一操作的前提条件是:将冲突缩小到单个分片的范围。(这就是文中说的回到耦合架构,因为DB需要通过key来感知哪些数据需要放在相同的分片中)。这对于rename以外的所有操作都成立。

image.png

上一小节说明了 Curve 文件系统的 dentry、inode 放置策略,这个设计也正好符合文中提到的抽象模型:影响元数据服务扩展性的根源是更新父目录属性时产生的冲突,这是关联变更的一部分。这里提到的父目录的属性,指的就是 inode 相关的属性。

但是在工程实践上,Curve 文件系统,对于同一个分片上的请求,是做不到像数据库这样使用同步原语解决。比如,对于 create dentry 的操作,在底层需要执行的操作是:

  • 操作1:创建 dentry,在 rocksdb 中插入一条记录
  • 操作2:修改父目录的 nlink,并修改 mtime,将新记录插入到 rocksdb 中

在并发情况下,这两个操作是无法通过同步原语的方式解决的,目前只能做到串行操作。这是影响性能非常关键的一点。对于这一点,从上层看从减少父目录的更新次数可以做请求的合并。长期看,提高 partition 上多类操作的并发度是非常必要的,比如一个很常见的 AI 场景,数据集的批量拷贝性能会大大受限。

沿用的NameSpace1.0的设计,关联元数据的存储放在DB中执行,文件属性的存储放在KV中。
这样做的好处是把负载分摊到了两个系统中。另外提到的一点是,如果单个目录下的文件数量很多,
DB的分裂可以保证该记录独占一个分片,最大能有单机处理能力,认为这个处理能力已经够强了。

在单个目录下文件数量过多的场景,Curve 文件系统做不到让它续展一个分片,因为当前分片上负责的 inode 范围是固定的。可以通过针对目录子项过大的情况,让新的 inode 不在创建的方式做兜底,后续也许可以考虑通过增加虚拟目录节点的方式来做迁移。

关于rename,很重要的一点是:根据我们的线上统计,99% 的 rename 都发生在同一个目录内文件间,这种 case 涉及到的变更都在一个 TafDB 分片内,可以采用前文提及的方法优化。
因此,我们将 rename 分为 Fast Path 和 Normal Path 两种。

Curve 文件系统,对 rename 做了两个版本的优化,都是使用的 2PC 事务,第一个版本 rename 在同一个文件系统上是全局排队的,第二个版本 rename 在同一个文件系统上源和目的不同可以并发。并没有考虑到从业务场景做一些优化。在看到上述统计信息的时候,很快就关联到在业务使用中很多时候都是从 rename A.tmp A 这类在同一目录下,为了避免一致性使用临时文件再做 rename 的场景。这也是 Curve 文件系统可以借鉴的 rename 优化途径。另外,我们发现 percolator 这样的事务模型在文件系统这样的场景下略显<笨重>,后续我们考虑使用事务管理器的方式来为一些操作提供原子性保障。

在工程优化上不仅考虑通用优化手段,也结合业务特征进行优化是 Curve 文件系统需要持续改进的部分。

总结


CFS 为性能做了大量设计和工程实践上的优化,我们通过分段解析,也看到了 Curve 文件系统很多可以优化的点,后续会持续跟进,也欢迎感兴趣的小伙伴的加入。如果上述的理解和描述有疏漏或者错误的地方、或者有一些新的想法,都欢迎在 Curve 社区指正和交流。

------ END. ------

🔥 开发者活动:

三校联动 | Curve Code Camp·金秋篇

🔥 用户案例:

Curve 文件存储在 Elasticsearch 冷热数据存储中的应用实践

扬州万方:基于申威平台的 Curve 块存储在高性能和超融合场景下的实践

创云融达:基于 Curve 块存储的超融合场景实践

🔥 技术解析:

CurveBS 1.5 版本功能介绍

CurveAdm v0.3.0 版本发布,集群运维更方便

Curve v2.7 发布:支持 Hadoop SDK,助力大数据存储降本提效

Curve 混闪之性能优化记录

CurveBS RDMA & SPDK 部署指南

image.png

关于 Curve 

Curve 是一款高性能、易运维、云原生的开源分布式存储系统。可应用于主流的云原生基础设施平台:对接 OpenStack 平台为云主机提供高性能块存储服务;对接 Kubernetes 为其提供 RWO、RWX 等类型的持久化存储卷;对接 PolarFS 作为云原生数据库的高性能存储底座,完美支持云原生数据库的存算分离架构。

Curve 亦可作为云存储中间件使用 S3 兼容的对象存储作为数据存储引擎,为公有云用户提供高性价比的共享文件存储。**


OpenCurve
1 声望0 粉丝

CNCF sandbox 项目,分布式存储系统 Curve 社区官方账号,提供 Curve 版本更新、落地实践、关键技术解析和活动资讯,欢迎各位关注!