BeeGFS元数据优化
Posted lizhongwen1987
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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键值存储作为元数据存储引擎,元数据格式通常有两种:
- 以全路径作为key,元数据作为value
优势:路径解析非常高效(可以直接通过请求路径读取元数据),目录扫描方便(可以通过前缀扫描)
劣势:key占用空间较大,跨目录Rename代价大(需要对目录下的所有文件和子目录进行移动) - 以父目录id +(文件/目录)名作为key,元数据作为value
优势:跨目录Rename非常轻量(只需修改源和目标节点以及他们的父节点),目录扫描方便(可以通过父目录id扫描)
劣势:路径解析延迟较高(需要递归读取元数据直到目标节点),近根热点(层级越小,访问热点越明显,导致系统负载不均衡)
考虑到业务中Rename操作有较高的比例,结合BeeGFS本身的元数据管理机制,我们选择第二种方案(两个缺点,可以通过缓存及目录子树分区缓解)
Type | Key | Value | Partitioned by |
---|---|---|---|
file metadata | parent id,name | file inode | parent id |
directory access metadata | parent id,name | directory entry | parent id |
directory content metadata | id | directory inode | id |
- file inode:对应上文的FileInode内容
- directory entry:对应上文的DentryStoreData内容
- directory inode:对应上文的DirInode内容
举个例子:
创建子目录/A/B (假定/,A,B的id分别为1,2,3)
- 通过<1,A>获得A的access metadata。
- 通过<2,B>创建B的access metadata。
- 通过<3>创建B的content metadata。
创建文件/A/B/file(假定/,A,B的id分别为1,2,3)
- 通过<1,A>获得A的access metadata。
- 通过<2,B>获得B的access metadata。
- 通过<3,file>创建file的metadata。
解析路径/A/B/file (假定/,A,B的id分别为1,2,3)
- 通过<1,A>获得A的access metadata。
- 通过<2,B>获得B的access metadata。
- 通过<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,将有数倍的提升)。
以上是关于BeeGFS元数据优化的主要内容,如果未能解决你的问题,请参考以下文章