分布式文件系统 bluestore简介-ceph backend

bluestore : a faster backend for ceph

—–sage weil 的公开课导读

ceph创始人sage大叔前些日子在国际版的公开课里面介绍了根据ceph的特定环境定制的新的文件系统bluestore,用以作为ceph的存储后端,本文主要以sage的presentation:

“bluestore - a new faster storage backend for ceph”

为基础,简单的介绍bluestore的设计方案与性能分析,部分知识点会比较粗糙或有错误,欢迎各位指正,谢谢!。


主要内容:
1、ceph背景,目前状况;
2、POSIX简介,与ceph的问题;
3、第一版解决方案 new store;
4、新一代解决方案 bluestore;
5、性能分析 ;
6、总结 ;


一、Motivating

ceph从一开始问世到目前已经接近了十年时间,从最开始的sage 的论文中对CEPH的文件系统描述:

“a scalable, high performance distributed file system”

sage说,作为ceph存储的后端,他强调“performance, reliability, and scalability”三大核心发展方向,可靠性和拓展性相对简单,而性能便一直是最具有挑战性的课题。
如下是经典的ceph的架构逻辑,ceph向外提供了三大接口,用以提供不同的存储功能,底层都是建立在RADOS之上,具体的rados内容可以参考weil的学术论文。
分布式文件系统 bluestore简介-ceph backend_第1张图片

从结构拓扑看,每个集群都可以看做是一棵树,主机作为数据的叶子节点,主机根据分工不同可以作为数据存储节点,也可以作为元数据存储节点,在存储节点上,最底层是磁盘,磁盘上是文件系统,目前主要的包括btrfs、xfs、ext4等POSIX标准文件系统,上层就是我们的OSD守护进程,用来维护对象的存储操作与映射等内容:
分布式文件系统 bluestore简介-ceph backend_第2张图片

由于ceph的数据的特殊结构,在实际的生产实践中,我们在标准的文件系统之上又增加了一层模块—Filestore:
分布式文件系统 bluestore简介-ceph backend_第3张图片

filestore在旧版本的Ceph中作为与文件系统的桥梁,用来暴露接口给上层OSD daemons来存储本地数据,他负责实际的写数据的交互逻辑。
对于FileStore的实现称之为对象存储ObjectStore,提供给ceph存储对象数据到物理磁盘的一系列接口,他的核心要素包括三部分:
a)对象object,可以映射为我们需要存储的中的文件,不论使用何种方式存储何种类型的数据,经过ceph最终都换转换成为一个object,它包含基础数据、对象属性数据attributes以及一些用来维护的omap数据,attributes是该对象的拓展属性,相当于POSIX类文件系统的元数据,受于底层文件系统的限制,这种k/v型的数据大小、个数是有上限的,一旦我们需要的该文件的描述信息无法存到其中,就需要存储到omap中,他会在fs之上存储在内存数据库中(leveldb)。
b)集合collections,简单的理解,可以类比文件系统中的目录结构,但是经过OSD daemons处理过后,向下传递的对象数据更加有序并且归置效果更高,对其分组更类似于一对对象的集合概念。对底层的POSIX文件系统而言,ceph拥有一个大的对象池,并将其分片城多个placement groups,这些pg会map到各个OSD,从而map到对应的object。
c)所有的写入都应该是事务的,否则对于一个分布式的存储解决方案而言数据的有效性将变得无法预知,所以所有的写入操作都应符合ACID特性;在ceph的架构中,从文件到OSD的映射已经处理了I的问题,ACD的维护需交由本地的存储系统来处理。
基于以上的核心观点,sage团队首先做了一个叫做EBOFS(a user-space Extended-Base Object File System)的FS,他是一个文件系统拓展,主要核心逻辑使用b-tree来实现,前期主要是做开发性质使用,未投入到生产中。后续由于btrfs的出现,并且很多功能btrfs和EBOFS有重叠,并且btrfs在社区中不断地被改进,sage团队一段时间内转战btrfs中。关于ebofs具体内容在sage的论文中有介绍。
那么问题来了,看似以上的方案无可厚非,then why POSIX failed us?
POSIX接口定义了操作系统层级的文件系统接口定义规范,但是作为早期的接口规范,他并没有考虑到大规模分布式场景的需求,在实际使用中暴露出一些问题。
首先POSIX规范中对数据更新以及元数据的根系都是懒惰的更新方式,自此他无法提供事务的数据或元数据操作接口,但是ceph为保证一致性他的数据操作都非常的精细,写入数据反馈不及时。使用上常规的写日志、写数据等操作相对简单,但是其他的操作可能会有无法判断的复杂度或资源占用。
后续在btrfs上出现了对事物的支持,btrfs提供了一种叫做事务钩子的接口(transaction hook,有兴趣的或了解的请帮忙补充),经测试后发现有场景下会造成系统宕机,在OSD进程意外夯住的情况下,事务无法在btrfs正确结束,导致资源的持续占用,最终拖垮整个os。
同时,对于POSIX的写前日志以及快照等相关的数据正确性维护措施相对繁杂,journal的维护也是全亮的,实际的磁盘存储能力会对半下降。
另外,POSIX的最初设计考虑的就是类似我们现在的PC场景,层叠的目录结构,完全无法归纳的文件类型和标识,随机的存储向不同的dir等。但在ceph中,经由OSD处理后,对象的标示转为32位的哈希数据,相对非常易于归纳,如果还继续按照POSIX的方式就会无法提供高效接口。ceph要求对数据分片时复杂度为O(1),但POSIX无法完成(想象下在你的某个盘符下对乱七八糟的百万个文件或目录进行分片)。而且在枚举时,POSIX很慢,而且一旦基数变大,资源消耗会大幅升高,在ceph中,可以对哈希值等前缀进行排序、分片,如果常驻内存,效率则会大大增加。


二、NewStore

为规避上述问题,我们需要改变接口模块,解决如下问题:
更线性化的原子事务,高效的枚举、克隆、追加(splice);尽量避免双份写入(journal),以及优化IO格式使对高性能存储设备存储更凸显性能(ssd nvme etc.),代码机构上最小化锁概念,最大化并行,以及数据、元数据的校验和功能(btrfs实现)、数据行内压缩等。
POSIX整体上的数据模型不适应ceph的实际要求(object≠file,collection≠directory),一个ordered k-v型数据库能够满足需求:对象经过OSD daemon处理后按照名称已经排好序,存入ordered k-v型数据库枚举以及随机查找将会更加高效;
分布式文件系统 bluestore简介-ceph backend_第4张图片
NewStore =rocksdb + object files(持久化的对象数据)
Rocksdb用来存储文件系统的元数据(metadata),对象的数据仍将存储在POSIX中;
*问题:
A) rocksdb自身有写前journal用来维护一致性,POSIX类文件系统自身也有log file,这种journal-on-journal的结构层次似的维护的开销巨大,并且每个journal只能保证部分一致性;
B) ceph需要对object数据进行覆盖写(事务提交之前原始数据不可更改),但POSIX不支持原子的重写事务,如果变通的在新的文件中写入则会是同一个数据面临很多的版本,对此尝试使用Write-Ahead-Logging:先将重写的数据写入wal(rocksdb),提交事务,重写原始数据,这样又出现了双份日志的情况,性能很差,于是出现新的存储后台 bluestore。*


三、 BlueStore

本章节将介绍bluestore的架构、设计,以及bluestore的基础元数据类型、匹配规则等,然后从数据映射流程讲解bluestore的实现方式。

3.1 bluestore介绍

Bluestore 建立在块设备之上,采用rocksdb作为元数据存储,数据直接在块设备上写入,bluestore自己实现了委派规则(allocation code,to allocate which block-device shall be written);关键点(key-challenge):块设备需要与rocksdb共享,包括持久化数据、日志等需要写入块设备中,自此实现自制的rocksdb,并实现了最简化的文件系统bluefs用来做元数据的基本读写操作,并与bluestore共享块设备信息。

Bluestore= bl ock(device) + N ewStore

逻辑架构如下:
分布式文件系统 bluestore简介-ceph backend_第5张图片

Rocksdb:基于in-memory的数据库引擎,用以存储映射关系、元数据等内容。 底层使用bluerockenv以及bluefs: Bluerockenv:rocksdb的后台,捕获所有的io操作并传递给bluefs处理 Bluefs:非常简单的文件系统: 
A)所有元数据放在内存中,并在系统或设备初始化时完成,因此无需存储块设备的free list,因为每次初始化的时候已经计算完毕的数据会实时在内存中 
B)届于ceph存储的数据为大批量的大块数据,因此,allocation code 分配的块大小为1M 
C)所有元数据都写在日志中,因此每次写日志的时候会同步更新fnode(inode) 
D)Journal在到达一定大小后会压缩 
E)Bluefs能够匹配不同的目录结构到不同的块设备中(hdd、ssd etc.) F)Bluestore 和bluefs相互通信,当bluefs的存储空间不足时,会通知bluestore分配更多空间给bluefs,如果bluestore自身空间不足,并且bluefs中尚有剩余时,bluefs会归还部分空间

实际在生产测试的时候发现Rocksdb的一些问题:Rocksdb的日志记录方式只有两种,读至文件末(需要文件大小)和读到标识符,这种方法在追加时需要修改自身元数据信息,自此文件的读写会增加IO,测试是一次3-4k的数据写入需要3-4次IO!sage将目前较为普遍的循环缓冲日志(circular buffer)中,以此减少IO;

3.2 Bluestore meta-data

所有的元数据在bluestore架构中都保存在rocksdb中,不同的元数据根据分工不同遵循分区的命名空间规则:

S* superblock  block size、configure options,整个存储的核心数据
B* block allocation: freeblock、block that used
C* collection name -> cnode_t
O*对象名存储到ONODE的映射关系
L* wal 写前日志
M*元数据信息
Etc.....

对象存储数据由以下structure之间的相互映射关系map到磁盘
Cnode:Collection metadata存储 cnode信息,格式如下:
分布式文件系统 bluestore简介-ceph backend_第6张图片

Onode:对象元数据 object metadata
每个对象节点元数据直接以k-v形式存在,可以序列化到最多200字节,存储大小的单位为字节(逻辑开销),每个对象会生成一个唯一的对象ID;ONODE还包含对象的Inline attributes(attr data基础元数据信息),以及数据指针,用以链接数据的物理存储对象的位置(分两层i.逻辑拓展->blob区域;ii. blob->disk):也包括Omap前缀,用以链接用户的k-v键值数据存储位置(对象的描述信息,与attr区别前面已经将过了)

数据结构设计:
分布式文件系统 bluestore简介-ceph backend_第7张图片

Bnode(blob metadata)/ Enode(extend metadata):拓展信息
在ONODE中对象的映射关系有从逻辑位置到blob,以及从blob中定位具体的数据位置,由于设计逻辑,相同的block中可能会被两个以及以上的object所共享(克隆、快照、拼接),将BNODE从ONODE中剥离作为拓展信息,在后续sage的presentation中将之改为ENODE;
映射格式举例如下,hash之前是enode信息:
分布式文件系统 bluestore简介-ceph backend_第8张图片
另外,在数据的存储时无法避免会出现诸如磁盘坏道等不确定因素,需要在文件系统层级对数据进行校验,bluestore采用校验和的方式(checksum),为保证数据的准确性,我们希望每次驱虎数据时做校验,为此必需在 元数据中存储校验数据,关于校验和CRC32的内容请自查,具体的校验块的大小可以自行设定或重新开发,sage在做介绍时还很模糊。
另外还有数据压缩工作(data compression),涉及内容目前尚不明确,后续对bluestore的改进中可能会逐步优化。

3.3 DATA PATH

本节主要阐明数据从OSD到实际的物理磁盘的映射过程的相关模块,在此之前先介绍如下术语:
A)sequencer:一个独立的全量有序的事务队列流,每个sequencer会map到特定的一个PG;因此在整个objectstore 层可以有成百上千个sequencer来使之并行工作,
B) transContext:每个sequencer拥有多个transaction,每个在内存中进行工作的事务都被称作一个transContext。

共有两种bluestore写数据的方式:
A) new allocation:如果写入数据大于min_alloc_size,bluestore 就会分配一个新的未使用的空间,然后再修改元数据,完成IO操作后,再提交rocksdb中的事务
B) WAL,如果写入数据小于min_alloc_size,bluestore会先写到write-ahead-log中,然后提交事务并承诺会完成磁盘写操作,然后再异步的写数据到磁盘中

*注:具体的阈值大小可能按照不同的磁盘读写习惯来更改,例如,HDD64k,SSD4k*

事务状态机如下:
分布式文件系统 bluestore简介-ceph backend_第9张图片

缓存模块:
Bluestore实现了自己的缓存机制,定义了structure :OnodeSpace,用来map 到内存中的ONODE;BufferSpace,用来map 块信息blob,每个blob都在bufferSpace中缓存了状态数据。二者在缓存中依照LRU的方式决定生命周期。
FreelistManager模块:
FreelistManager用来映射磁盘的使用信息,最初实现是采用k-v的方式来存储对应的磁盘块的使用情况,但是由于更新数据时需要修改映射,需要线程锁来控制修改,而且这种方式对内存消耗很大;后续修改为bitmap的映射方式,设定一个offset来以bitmap的方式map多个block使用信息,使用XOR计算来更新块的使用情况,这种方式不会出现in-memory 状态。
Allocator模块
如前所述,用来委派具体哪个实际存储块用来存储当前的object数据;同样采用bitmap的方式来实现allocator,同时采用层级索引来存储多种状态,这种方式对内存的消耗相对较小,平均1TB磁盘需要大概35M左右的ram空间。


四、 性能数据
性能数据主要和之前的文件系统组件版本filestore相比较:
1、顺序写:在大文件写的时候,之前的filestore由于需要double write(journal问题)导致基本两倍域bluestore的开销。
分布式文件系统 bluestore简介-ceph backend_第10张图片
2、随机写 基本也是两倍的速度提升,右侧在32K和64K之间出现波峰的原因是64K为min_alloc_size,采用wal代替直接委派新块空间,从而提升吞吐率
分布式文件系统 bluestore简介-ceph backend_第11张图片
3、顺序读
分布式文件系统 bluestore简介-ceph backend_第12张图片
4、随机读,左方是IO吞吐量,右方是IO吞吐率
分布式文件系统 bluestore简介-ceph backend_第13张图片


五、总结

到此对bluestore的介绍基本完成,本文主要是从架构和设计的方向对分布式文件系统 bluestore进行阐述,从ceph的jewel版本之后可以陆续的看到bluestore的身影,sage在presentation中强调会在kraken版本的时候基本达到生产要求。到目前ceph,大家可以从git上查看设计代码了。

后续我大概还会整理crush的代码设计、以及相关的分布式设计理念等等~~~~~
本文有任何错误、纰漏内容欢迎指正,另附一些链接,可以快速查看相关内容拓展~~~~~

原创内容,转载请注明出处~~
Appendix:
1 【顺序读和随机读】http://www.violin-memory.com/blog/understanding-io-random-vs-sequential/
2 【rados】http://ishare.iask.sina.com.cn/f/36655999.html
3 【sage的 公开课】
http://mp.weixin.qq.com/s?__biz=MzA3NjkwNjM4Nw==&mid=2651868098&idx=1&sn=e27c94b4e311d229bd40e9ea27009e7a&chksm=84bec13eb3c9482811ef9adce98828ebaf8205306109a941607ffbd5ba2fe2688c97b8d86167&scene=0#rd
4 【ceph 社区文档】http://docs.ceph.org.cn/

个人微信公众号:
分布式文件系统 bluestore简介-ceph backend_第14张图片

你可能感兴趣的:(ceph)