2.5 BlueFS
简易用户态日志型文件系统,实现RockDB::Env定义的全部接口,固化运行中产生的.sst(SSTable)和.log(WAL文件),两者存储分离。
存储层级:
慢速(Slow)空间:存储对象数据,HDD提供,Bluestore自行管理,与BlueFS共享空间也是由BlueStore直接管理,Bluestore会将所有已成功分配的空间段单独用bluefs_extents结构进行管理,从自身Allocator中扣除。
|
\/
高速(DB)空间:存储Bluestore元数据(onode),SSD提供,BlueFS管理
|
\/
超高速(WAL)空间:RocksDB产生的.log文件,NVME/SSD提供,BlueFS管理
DB和WAL上电时BlueFS负责初始化,上电初始化3个Allocator实例,分别管理3中可用空间。
和Bluestore固化空闲空间列表不同,BlueFS不保存空闲空间列表或已分配空间列表,而是上电遍历元数据信息,生成完整已用空间列表Allocator。
BlueFS磁盘数据文件
包括文件、目录、日志三种类型。

dir_map的每个条目描述都是文件的绝对路径,条目间无隶属关系,每个文件也用类似inode结构进行管理,BlueFS称bulefs_fnode_t(fnode)。file_map建立的实际上是文件名和fnode的映射关系。
BlueFS需要定期进行日志清理(日志压缩),将当前dir_map和file_map加入独立日志事务并存盘(写异步)。上电通过日志重放来得到BlueFS所有元数据,需要一个固定入口用于索引日志。此入口称超级块(SuperBlock),BlueFS将其写入自身接管DB设备的第二个4K存储空间。


2.6 实现原理
mkfs 固化用户指定配置项到磁盘

mount 正常上电前的检查和准备工作
(1)校验ObjectStore类型
(2)fsck或deep-fsck,扫描并检验Bluestore中所有元数据
(3)加载并锁定fsid
(4)加载主块设备
(5)加载数据库,读取元数据
(6)加载Collection,常驻内存


read 同步读取对象指定范围内的数据
(1)查Collection

(2)查Onode
每个Blob包含一个SharedBlob,其主要内容为一张基于pextent的引用计数表,对应的内容即为被引用的次数。SharedBlob还包含BufferSpace,用于对Blob中的数据进行缓存,并纳入Cache管理。
引入SharedBlob后,每个Blob有shared和!shared两种状态,如果为shared状态,则该Blob被多个Onode共享。SharedBlob关联一张有效的引入计数表,进行按需加载。有需要使用时,才从kvDB加载至SharedBlob,此时SharedBlob状态变为loaded。

(3)读缓存
Onode直接缓存命中,可能部分数据已经存在于全局Cache中,Bluestore会先从Cache读取指定范围内的数据。
(4)读磁盘
如果全部or部分未在Cache命中,则需要去磁盘读。可加载Extent至内存再进行读取。
write
包括write在内的涉及数据修改的操作,都是通过queue_transactions以事务组的形式提交至BlueStore的。

OpSequencer:对同PG提交的多个事务组进行保序。
同一事务的多操作当然会用到事务上下文,TransContext就是记录这个修改操作的顺序的。
写抑制判断是否过载,由Throtte进行。
所有通过queue_transactiions提交的事务组都是异步执行的,需要指定若干种类的回调上下文,即下文事务组执行到某阶段后,上文被唤醒执行相应操作。常见两种回调上下文是:
(1)on_readable
日志修改操作先写入前端较快日志设备,写完返回日志完成应答
(2)on_commit(on_disk&on_safe)
数据落存储盘。
Bluestore直接先on_commit再on_readable,因为写操作只能产生少量WAL日志,且WAL日志也是一种元数据,直接一起在kvDB保存了。
Write加入TransContext流程:

MAS对齐:

非MAS对齐写和MAS对齐写区别:

新写和覆写:
新写按逻辑地址范围看是否要进行MAS,覆写复杂一些



新写内容不足一个unused块,则填0




WAL写包括补齐读+合并+填充,完成后BlueStore生成一个日志事务,再加入TransContext。这套流程搞完,写入kvDB后,原区域才开始执行覆写,效率很低。
所有修改操作都加入TransContext时,开始处理相关事务,经由以下3阶段:
(1)等待所有在途写I/O完成:写I/O主要是非WAL写通过COW产生的I/O,同步性事务。
(2)同步所有涉及的元数据修改至kvDB:同一事务组中所有事务一起提交,ACID属性。
(3)通过WAL对应的日志事务执行覆盖写
2.7 使用指南

slow:DB:WAL = 100:1:1(最佳配比?待验)