Ceph RGW multisite代码实现

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状态。

Ceph RGW multisite代码实现_第1张图片
rgw中的协程设计

同步实现

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

  • meta data同步。包括bucket相关对象和user相关对象(user.uid namespace 下的uid信息和root namespace下的bucket以及bucket-instance信息),位于.rgw.meta pool中。元数据同步可以类比为手动在本地zone创建bucket和user。
  • data同步。即每个bucket下的对象。data数据同步可以类比为手动在本地上传/删除bucket下的对象。

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

Ceph RGW multisite代码实现_第2张图片
三个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当前同步进度(用marker表示)。
.rgw.log pool中的meta.full-sync.index.对象用omap来存储从master zone的.rgw.meta pool拉取的数据(pool下的对象名, full-sync时使用)
.rgw.log pool中的meta.log..对象用omap来存储元数据操作log,比如创建bucket时,master zone的对象上会增加一条log记录,slave zone从master zone来获取这些记录,从而得到需要从master拉取的数据的列表(bucket名字),然后对bucket元数据做同步。这种同步方式属于incremental-sync。

代码实现

Ceph RGW multisite代码实现_第3张图片
metasync流程RGWRemoteMetaLog::run_sync()

data的同步

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

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

代码实现:

Ceph RGW multisite代码实现_第4张图片
data数据同步
Ceph RGW multisite代码实现_第5张图片
一个bucket的同步过程

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

你可能感兴趣的:(Ceph RGW multisite代码实现)