暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

趣解 ceph rgw multisite data sync 机制

Ceph运维技巧及源码分析 2019-05-27
1414

'小白打怪' 公众号记录了 非存储相关专业 的 小白 毕业入职 后,四年多在存储领域学习打怪升级的过程,文章干货满满,有趣易懂,非常适合Ceph初学者阅读,欢迎关注同行,共同进步~



multisite sync是ceph rgw对象数据异地容灾备份的一个有效方案,然而rgw的这部分代码晦涩难懂,笔者读得云里雾里不解其意,流着泪咬着牙坚持多看了几遍,总结了data sync的概要流程,这里以通俗易懂的形式呈现出来,希望对大家有所帮助~


一、认识下 data sync机制 的三个角色Data、DataLogShard、BucketShard

rgw的multisite sync分为两部分:metadata sync 和 data sync。metadata包括bucket信息、bucket instance信息、user信息等;data指的是存储对象的实际数据,记为Data。本文将介绍data sync。

rgw使用datalog来记录Data的变化,为防止datalog成为瓶颈,将datalog分成了 ${rgw_data_log_num_shards} 个shard,即DataLogShardDataLogShard记录了Data的变化。

rgw使用bucket index来提升list对象的效率。为防止bucket index成为瓶颈,将bucket分成了 ${rgw_override_bucket_index_max_shards}BucketShard。每个BucketShard的bucket index log记录了该BucketShard内对象的变化。

rgw的每个BucketShard都会通过hash映射到某个DataLogShard上,形成了如下形式的映射关系,理解这层映射关系是理解data sync的重要前提。

    DataLogShard ...   :   ...
    DataLogShard 12 : bucket_a:0bucket_b:3
    DataLogShard 13 : bucket_a:4bucket_b:7bucket_c:5 ...
    DataLogShard ... : ...

    当某个BucketShard内的数据发生变化时,对应的DataLogShard的datalog会记录哪个BucketShard发生了数据变化。

    二、讲完data sync的三个角色,下面切入正题讲个关于data sync的故事

    故事是这样的,北京rgw想要开拓上海的市场,于是派DataSync去上海创建rgw并负责把北京rgw的数据资源同步到上海rgw,即data sync(北京rgw -> 上海rgw)。

    老大DataSync到达上海,来管控整个data sync流程的进度。前面说了DataLogShard记录了rgw Data 中 BucketShard的变化。老大DataSync决定招聘${rgw_data_log_num_shards} 个 小弟DataLogShardSync 来负责将北京rgw中的数据同步到上海rgw,每个小弟负责北京rgw的一个DataLogShard。老大DataSync想,数据同步工作不是一蹴而就的,他需要记录下data sync的进度来,才能防止意外的同步失败而导致需要从头开始数据同步。

    于是老大DataSync用名为rgw_data_sync_info的记录来规划了他第一阶段工作为StateInit,并记录了他有 ${rgw_data_log_num_shards} 个小弟DataLogShardSync要进行数据同步工作。

       struct rgw_data_sync_info { uint16_t state; uint32_t num_shards;}

      ① 老大DataSync::StateInit:

      老大DataSync需要给他 num_shards 个小弟DataLogShardSync设定目标,就是小弟DataLogShardSync需要工作到上海rgw的数据赶上北京rgw的数据更新进度。于是老大DataSync打电话到北京rgw获取了各个DataLogShard数据的最新marker并记录成小弟的next_step_marker,并记录各个小弟DataLogShardSync的同步状态为FullSync,整理到rgw_data_sync_marker中 ,小弟DataLogShardSync在FullSync阶段的工作就是同步数据到这个marker

        struct rgw_data_sync_marker {uint16_t state; string next_step_marker;}


        老大DataSync将自己的工作进度(rgw_data_sync_info )和各个直属小弟的工作进度(rgw_data_sync_marker)都记录了下来到了rgw_data_sync_status中。 

          struct rgw_data_sync_status {
          rgw_data_sync_info sync_info; // 记录data sync的整体同步进度
          map sync_markers; // 记录每个DataLogShard的同步进度
          }


          这样,老大DataSync做完了第一阶段StateInit的工作,规划做下一阶段StateBuildingFullSyncMaps的工作。

          ② 老大DataSync::StateBuildingFullSyncMaps:

          老大DataSync说,北京rgw的datalog会进行trim,如果通过datalog来同步数据到上海rgw,会导致一些数据同步不过来,所以需要进行下FullSync。FullSync就是将小弟DataLogShardSync都管辖着的各个BucketShard中的对象逐一list出来,然后从北京rgw传输到上海rgw。因次需要知道小弟DataLogShardSync分别管辖着哪些BucketShard。老大打电话问了北京rgw,并将这些信息(每个DataLogShard下有哪些BucketShard)记录下来。
          这样,老大DataSync做完了第二阶段StateBuildingFullSyncMaps的工作,规划下一阶段StateSync的工作。

          ③ 老大DataSync::StateSync:

          老大在这个阶段的主要工作是,监督小弟工作,老大前面已经规划了小弟的第一阶段工作是FullSync,小弟DataLogShardSync于是开始按部就班的工作。

          ④ 小弟DataLogShardSync::FullSync:

          小弟DataLogShardSync为每个BucketShard招募了一个小喽啰BucketShardSync来为其工作,使用rgw_bucket_shard_sync_info来记录每个小喽啰的工作情况。

            struct rgw_bucket_shard_sync_info {
            uint16_t state;
            rgw_bucket_shard_full_sync_marker full_marker;
            rgw_bucket_shard_inc_sync_marker inc_marker;
            }


            同样地,小弟DataLogShardSync需要给下属的各个小喽啰BucketShardSync安排工作。小弟将小喽啰BucketShardSync的第一个阶段工作设定为StateInit。嗯,小弟的工作完成了,轮到小喽啰干活了。

            ⑤ 小喽啰BucketShardSync::StateInit:

            虽然小弟没有给下属小喽啰设定目标,但小喽啰BucketShardSync很自觉,自己打电话给北京rgw问到了其负责的BucketShard的最新marker,然后记录到自己的rgw_bucket_shard_sync_infoinc_marker中。意思是,要先full sync(全量同步)到这个marker,然后从这个marker开始inc sync(增量同步)。
            这样,小喽啰的第一阶段工作完成了,准备进入下一阶段StateFullSync

            ⑥ 小喽啰BucketShardSync::StateFullSync:

            在这个阶段,小喽啰会批量从北京rgw查询其负责的BucketShard中的对象,同步到上海rgw,并持续更新full_marker,直到full_marker等于自己的rgw_bucket_shard_sync_infoinc_marker。结束后,小喽啰规划进行下一阶段工作为StateIncrementalSync

            三、full sync(全量同步)结束,进入inc sync(增量同步阶段)

            ⑦ 小弟DataLogShardSync::IncrementalSync:

            完成了full sync,可以根据datalog的变化来inc sync了。小弟DataLogShardSync打电话问北京rgw自从上次同步点,有哪些BucketShard发生数据变更。然后,安排负责这些发生数据变更的BucketShard对应的小喽啰单独进行工作。

            ⑧ 小喽啰BucketShardSync::StateIncrementalSync:

            小喽啰打电话到北京rgw,问从自己的inc_marker开始,自己负责的BucketShard具有有那些数据变更,然后根据数据变更来同步数据。

            至此,data sync的故事讲完了

            友情出演:
            老大DataSync:
                控制着整个data sync流程的同步进度。标识进度的状态有三个:StateInit、StateBuildingFullSyncMaps、StateSync。
            小弟DataLogShardSync:
                控制着一个DataLogShard的同步进度。标识进度的状态有两个:FullSync、IncrementalSync。
            小喽啰BucketShardSync:
                控制着一个BucketShard的同步进度。标识进度的状态有三个:StateInit、StateFullSync 、StateIncrementalSync。

            番外篇:
            上海rgw的所有工作人员集体出走了,上海rgw新招了一堆新人,如果保持数据同步呢?新人根据 rgw_data_sync_info 获知rgw data sync的进度为StateSync,然后根据 rgw_data_sync_marker 获知各个DataLogShard的同步状态为IncrementalSync,然后根据 rgw_bucket_shard_sync_info 的获知各个BucketShard的同步进度为StateIncrementalSync。于是,轻松交接工作,继续干活同步数据,即
            DataSync::StateSync -> DataLogShardSync::IncrementalSync -> BucketShardSync::StateIncrementalSync

            Sync大流程:


            Done

            文章转载自Ceph运维技巧及源码分析,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论