BeeGFS元数据优化

目标

用KV键值存储(如:rocksdb)替代本地文件系统(如:ext4),作为BeeGFS的元数据引擎,提升元数据处理能力

现有技术概述

文中设计的数据结构基于BeeGFS 7.2.2代码

一句话总结:基于目录的静态分区方式,文件与父目录放在一起(本地化)

文件系统初始化时,根据先来后到原则,选取第一个(注册成功)的元数据节点(组)作为系统根节点,根据根目录ID的hash值将根目录(root)预置于根节点的38/51/root路径下;

创建子目录时,父目录随机选择一个元数据节点(组)作为该子目录的服务节点,创建子目录的元数据操作如下:

1、在子目录的服务节点,根据子目录ID的hash值创建目录项(目录):dentries/xx/yy/ d e n t r y I D , 创建文件 I D 目录: d e n t r i e s / x x / y y / {dentryID}, 创建文件ID目录:dentries/xx/yy/ dentryID,创建文件ID目录:dentries/xx/yy/{entryID}/#fSiDs#

2、在子目录的服务节点,根据子目录ID的hash值创建索引节点(文件):inodes/xx/xxy/${dentryID}, 索引内容存放在key为user.fhgfs的扩展属性中(限制大小为4KB)

【持久化涉及的结构:DirInode,StatData,StripePattern,StripePatternHeader,SettableFileAttribs】

3、在父目录的服务节点,在父目录下创建目录项(文件):dentries/mm/nn/${dentryID},目录项内容存放在key为user.fhgfs的扩展属性中(限制大小为4KB)【持久化涉及的结构:DirEntry, DentryStoreData】

4、在父目录的服务节点,更新父目录的索引节点(文件)

注:子目录的服务节点(组)和父目录的服务节点(组)(大概率)可能不同

创建文件时,文件元数据放在与父目录相同的元数据节点(组)上:

1、在父目录的服务节点,在父目录的文件ID目录创建文件索引节点(文件):dentries/xx/yy/KaTeX parse error: Expected 'EOF', got '#' at position 12: {dentryID}/#̲fSiDs#/{file_dentryID},索引内容存放在key为user.fhgfs的扩展属性中(限制大小为4KB)

【持久化涉及的结构:DirEntry,DentryStoreData,FileInodeStoreData,StatData,StripePattern,StripePatternHeader,SettableFileAttribs, ChunksBlocksVec】,在父目录的目录项(目录)创建文件目录项(文件):

dentries/xx/yy/ d e n t r y I D / {dentryID}/ dentryID/{file_name},它是指向上述索引节点的硬链接

2、在父目录的服务节点,更新父目录的索引节点(文件)

打开文件时,元数据操作如下:

1、在父目录的服务节点,加载索引节点文件:dentries/xx/yy/KaTeX parse error: Expected 'EOF', got '#' at position 12: {dentryID}/#̲fSiDs#/{file_dentryID},实例化FileNode对象加入到父目录的inodes映射表并添加引用计数、读/写会话数、父目录引用计数

【涉及的结构:FileInodeStoreData,StatData,StripePattern,StripePatternHeader,SettableFileAttribs, ChunksBlocksVec,ChunkFileInfo,DynamicFileAttribs,DentryCompatData】

元数据管理中所涉及的核心数据结构如下:
元数据核心数据结构

  • 每个mds包含一个MetaStore单机存储引擎,以Ext4为基础,将元数据存储在文件的扩展属性中,其包含InodeDirStore和InodeFileStore两个子引擎
  • InodeDirStore子存储引擎以目录为单位管理本MetaStore引擎中所有的子目录和文件, 一个DirNode代表一个目录索引节点Inode,包含该目录的详细元信息,其通过InodeFileStore来管理其下的所有文件,一个DentryStoreData代表一个目录Dentry,
  • InodeFileStore子存储引擎,包含2个:一个全局的暂存引擎,用于暂存该MetaStore引擎中的孤儿文件、延迟删除文件;一个每目录的文件引擎,用于存储该目录下的文件Dentry及Inode, 一个FileInode代表一个文件索引节点Inode,包含该文件的详细元信息,文件dentry硬链接到Inode。

为便于理解,下图是一个示例:
目录树示意图

  • 根目录(/):目录项ID为:root,目录项路径为:dentries/38/51/root, 索引节点路径为:inodes/38/51/root
  • 文件(File1):目录项ID为:1-626E6AF2-B, 文件名为:File1, 目录项路径为:dentries/38/51/root/File1, 索引节点路径为:dentries/38/51/root/#fSiDs#/1-626E6AF2-B, 目录项文件硬链接到索引节点文件
  • 目录(Dir1):目录项ID为:0-626E6C1F-B, 目录项路径为:dentries/8/62/0-626E6C1F-B, 索引节点路径为:inodes/8/62/0-626E6C1F-B
  • 文件(File2):目录项ID为:0-626E6FA3-B,文件名为:File2, 目录项路径为:dentries/8/62/0-626E6C1F-B/File2, 索引节点路径为:inodes/8/62/0-626E6C1F-B/#fSiDs#/0-626E6FA3-B

注:根据负载均衡算法,Dir1可能与根目录分布在不同的元数据节点上,我的示例中凑巧在一个元数据节点上

引擎KV化

petrelfs mds采用本地文件系统(如:ext4)中的文件(及扩展属性)来管理petrelfs系统中目录及文件的元数据,具体的:

1)一个petrelfs文件:在父mds中包含一个目录项文件(硬链接到inode文件),一个inode文件(扩展属性中存储元数据)。
2)一个petrelfs目录:在父mds中包含一个目录项文件(包含DentryStoreData),在mds中包含一个inode文件(扩展属性中存储元数据),一个目录。

每次更新文件和目录时,会更新其inode文件扩展属性,每次获取文件属性时,会读取其inode文件扩展属性;受限于本地IO栈:

1)本地文件系统的强POSIX语义接口调用,用户态/应用态切换,导致性能低下
2)Linux IO栈层次众多,管理复杂,重复拷贝,造成额外开销及性能损失,无法发挥NVMe介质性能

当前已有众多的解决方案引入KV store来构建文件系统,我们选择rocksdb键值存储作为元数据存储引擎,元数据格式通常有两种:

  1. 以全路径作为key,元数据作为value
    优势:路径解析非常高效(可以直接通过请求路径读取元数据),目录扫描方便(可以通过前缀扫描)
    劣势:key占用空间较大,跨目录Rename代价大(需要对目录下的所有文件和子目录进行移动)
  2. 以父目录id +(文件/目录)名作为key,元数据作为value
    优势:跨目录Rename非常轻量(只需修改源和目标节点以及他们的父节点),目录扫描方便(可以通过父目录id扫描)
    劣势:路径解析延迟较高(需要递归读取元数据直到目标节点),近根热点(层级越小,访问热点越明显,导致系统负载不均衡)

考虑到业务中Rename操作有较高的比例,结合BeeGFS本身的元数据管理机制,我们选择第二种方案(两个缺点,可以通过缓存及目录子树分区缓解)

TypeKeyValuePartitioned by
file metadataparent id,namefile inodeparent id
directory access metadataparent id,namedirectory entryparent id
directory content metadataiddirectory inodeid
  • file inode:对应上文的FileInode内容
  • directory entry:对应上文的DentryStoreData内容
  • directory inode:对应上文的DirInode内容

举个例子:

创建子目录/A/B (假定/,A,B的id分别为1,2,3)

  1. 通过<1,A>获得A的access metadata。
  2. 通过<2,B>创建B的access metadata。
  3. 通过<3>创建B的content metadata。

创建文件/A/B/file(假定/,A,B的id分别为1,2,3)

  1. 通过<1,A>获得A的access metadata。
  2. 通过<2,B>获得B的access metadata。
  3. 通过<3,file>创建file的metadata。

解析路径/A/B/file (假定/,A,B的id分别为1,2,3)

  1. 通过<1,A>获得A的access metadata。
  2. 通过<2,B>获得B的access metadata。
  3. 通过<3,file>获取file的metadata。

各位读者,可以将上述的示例与前文的元数据操作对比下,体会下差异:

对于目录:由content metadata的kv操作替代本地文件系统的dentry目录(包括#fSiDs#)和inode文件(包括扩展属性)创建操作,由access metadata的kv操作替代本地文件系统的dentry文件(包括扩展属性)创建操作

对于文件:由file metadata的kv操作替代本地文件系统的dentry文件及inode文件(包括扩展属性)创建操作,由content metadata的操作替代本地文件系统的inode文件(包括扩展属性)更新操作

通过用KV引擎替代本地文件系统,减少了元数据IO过程中的文件操作,再加上rocksDB的结构(LSM-T)优势,BeeGFS的元数据性能提升明显。(如果集成SPDK+rocksdb,将有数倍的提升)。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值