图解Ceph_003_BlueStore事务数据结构

CEPH VERSION: Quincy 17.2.6

在PG层即将调用ObjectStore层的时候,会组装ObjectStore层的事务,然后通过
ObjectStore::queue_transactions或ObjectStore::queue_transaction提交,区别是多个事务或单个事务提交。

ObjectStore层事务结构如下,这是个不针对具体存储方案的一般性描述


ObjectStore事务Types.png

ObjectStore层事务是抽象的,需要具体的ObjectStore实现来进行转换,才能真正与底层的Store组件匹配,最终完成IO落盘。所以,自然的,BlueStore会有自己的事务结构。

BlueStore::queue_transactions开始的时候,就会将一次提交的ObjectStore::Transaction转换为一个BlueStore::TransContext,注意是一次提交的多个上层的事务被转换为单个BlueStore事务。

转换发生在_txc_state_proc之前过程中,具体后文再分析,此处关注数据结构。转换后的BlueStore事务结构如下:


BlueStore事务Types.png

从上图可以看出来,本质上,事务由两个核心部分组成:

  1. 一个rocksdb::WriteBatch bat,所有元数据变更都被encode到了这个WriteBatch之中,最后被提交至RocksDB
  2. 若干个aio_t,包含所有数据变更,最后被提交至BlockDevice

至此不免会有些疑惑,BlueStore事务要更新RocksDB和BlockDevice两个地方,如何保证事务的原子性呢?

BlueStore的写策略综合运用了COW和RMW策略。新写直接分配空间写入即可;块大小对齐的覆盖写采用COW策略;小于块大小的覆盖写采用RMW策略。

新写和对齐覆盖写,都可以先分配空间,而后写数据到新位置,最后更新元数据到rocksDB,只要多个kv的rocksDB更新能够保证原子性,那么整个事务就具有原子性。

RMW则复杂一些,它本身是非原子操作,那么如何保证这个过程的原子更新呢?BlueStore的方案是,识别到这些RMW操作,将它们组装成bluestore_deferred_transaction_t,简称deferred_txn,而后将deferred_txn序列化成kv,合并放到rocksdb::WriteBatch中,一并提交给RocksDB,只要提交到了RocksDB,则有了持久化保证,正常情况下可以延迟做它的写盘操作,异常重启的情况下,可以通过回放来完成这些延迟写盘操作,一切就有保障。

所以,经过上述过程,BlueStore事务的原子性保证,就集中到了rocksdb::WriteBatch的原子性保证,而WriteBatch本就是一次RocksDB::Put()的原子操作集合,要么完全成功要么完全失败,并且提供read-committed事务隔离级别,所以事情就完美解决了。

下一篇接着分析BlueStore txc状态机,揭示事务的生命周期

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容