Ceph RGW multisite代码实现

2017-12-23  本文已影响0人  宋新颖

multisite代码中大量使用了Boost的协程,在了解协程的使用方法后,整体代码结构还是比较清晰的。

协程实现

rgw中的协程库使用的是boost库,boost库中corotuine实现原理是由基类保存函数当前执行位置,每次运行时根据switch判断要执行的位置,具体可参考asio/coroutine.hpp

一次同步操作是由多个RGWCoroutine实例完成,每个RGWCoroutine作为一个基础的op由一个RGWCoroutineStack管理,一个stack内会有多个op,但只有最新加入的op能获得执行机会,op执行完成后会被移除出stack队列,进而stack中下一个op获得执行机会。一个RGWCoroutineManager实例分层管理多个stack集合,最新层stack集合中的每个stack都有同等运行机会,一次RGWCoroutineManger::run()方法会新建一层stack集合,直到集合中的所有stack(即stack中的全部op)执行完毕后返回。一个op调用另一个op有两种方式:callspawncall方法在当前op隶属的stack上加入新的op,直到新op执行完后才会继续执行自己的代码;spawn方法会将新的op放到新建的stack中,新stack会被放到manager的当前层(最新层),从而两个op能并发执行(由于stack是顺序遍历的,所以两个op也是顺序执行的)。

每个coroutine op都要实现自己的operate()方法,manager在遍历stack list时会调用RGWCoroutine::operate(),一般情况下operate()方法结束时会调用set_cr_error()set_cr_done()表示op已经完成,但对于RGWMetaSyncShardCR等op,operate()返回时并没有设置完成标志,因此这个op会一直执行(重复被调用operate()方法),其parent也会一直处于waiting_for_child状态。

rgw中的协程设计

同步实现

multisite的功能是实现一个zone group内多个zone的数据同步。这里的数据被分成了两类:

启动rgw 实例时在RGWRados::initialize()中会启动相关的同步组件。对于meta data,每个rgw启动一个单独线程来执行同步,而对于data数据的同步,由于每个zone都需要向其他所有zone进行同步,因此会启动n-1个同步线程,每个线程负责本地到另外一个zone的同步。

三个zone时rgw同步线程的状态

meta data的同步

目的:rgw.metapool下的bucket对象,bucket-instance对象以及uid对象拷贝到本地,且为每个bucket创建shard对象。

辅助结构:
.rgw.log pool中的mdlog.sync-status对象存储本zone当前的元数据同步状态。
.rgw.log pool中的mdlog.sync-status.<shard>对象存储每个shard当前同步进度(用marker表示)。
.rgw.log pool中的meta.full-sync.index.<shard>对象用omap来存储从master zone的.rgw.meta pool拉取的数据(pool下的对象名, full-sync时使用)
.rgw.log pool中的meta.log.<period>.<shardid>对象用omap来存储元数据操作log,比如创建bucket时,master zone的对象上会增加一条log记录,slave zone从master zone来获取这些记录,从而得到需要从master拉取的数据的列表(bucket名字),然后对bucket元数据做同步。这种同步方式属于incremental-sync。

代码实现

metasync流程RGWRemoteMetaLog::run_sync()

data的同步

目的:将每个bucket下的对象拷贝到本地bucket下

辅助结构:
.rgw.log pool中的datalog.sync-status.<zone>对象存储本zone到目标zone当前的数据同步状态。
.rgw.log pool中的datalog.sync-status.<zone>.<shard>对象存储本zone到目标zone当前的数据同步进度。
.rgw.log pool中的data.full-sync.index.<zone>.<shard>对象的omap用来存储从目标zone的拉取的bucket-info信息
.rgw.log pool中的data_log.<shard>对象的omap中存放对象操作日志。当对bucket进行对象操作时,会在omap上新建一条"1_"+<timestamp> 开头的日志,表明这个bucket被修改过,增量同步时会根据这些日志判断出哪些bucket被更改过,进而再针对每个bucket进行同步。
.rgw.log pool中的bucket.sync-status.<src-zone>:<[tenant/][bucket-name:][bucket-id:][bucket-shard]>使用xattr存放对应bucket的同步状态
bucket shard对象omap中0x80+"0_"命名空间下的key记录了此bucket的对象操作日志,用于增量同步时使用。

代码实现:

data数据同步 一个bucket的同步过程

注意:
当zone之间的sync 网络不可用时,每个zone是可以本地操作上传和删除对象的。在网络恢复后,各个zone最后存在的版本将是modify-time最新的那次上传的版本。网络故障期间如果有个别zone执行了del操作,即使操作时间是最新的,此次del操作最终会被其他put操作覆盖掉。如果多个put操作的modify-time相同且文件内容不同,则按照short_zone_id大小比较(代码实现见obj_time_weight::operator<)。

上一篇下一篇

猜你喜欢

热点阅读