Introduction
BlueStore存储引擎实现中,需要存储数据和元数据。由于kv存储系统自身的高效性以及对事务的支持,所以选择kv存储元数据是理所当然的(对象的omap属性算作数据,也是存放在kv中的)。Luminous目前默认采用RocksDB来存储元数据(RocksDB本身存在写放大以及compaction的问题,后续可能会针对Ceph的场景量身定制kv),但是BlueStore采用裸设备,RocksDB不支持raw disk,幸运的是,RocksDB提供RocksEnv运行时环境来支持跨平台操作,那么能够想到的方案就是Ceph自己实现一个简单的文件系统,这个文件系统只提供RocksEnv需要的操作接口,这样就可以支持RocksDB的运行,而这个文件系统就是BlueFS。
作为文件系统本身,需要存放日志,保护文件系统数据的一致性。对于RocksDB,也可以对.log文件单独配置性能更好的磁盘。所以在BlueFS内部实现的时候,支持多种不同类型的设备(wal/db/slow),实现非常灵活,大致原则是RocksDB的.log文件和BlueFS自身的日志文件优先使用wal,BlueFS中的普通文件(RocksDB的.sst文件)优先使用db,当当前设备空间不足的时候,自动降级到下一级的设备。
文件系统本身需要使用磁盘空间存放数据,但是BlueFS并不需要管理磁盘空闲空间,它将文件分配和释放空间的操作记录在日志文件中。每次重新加载的时候,扫描文件系统的日志,在内存中还原整个文件系统的元数据信息。运行过程中,磁盘空间使用情况大致如下(借用Ceph作者Sage的图):
Data Structure
先看看在BlueFS中标识一个文件的inode:
// 物理磁盘的位移和长度,代表块设备的一个存储区域
class AllocExtent {
public:
uint64_t offset; // BlockDevice的物理地址
uint32_t length; // 长度
};
class