Ceph RGW multisite代碼實現

multisite代碼中大量使用了Boost的協程,在了解協程的使用方法后,整體代碼結構還是比較清晰的。

協程實現

rgw中的協程庫使用的是boost庫,boost庫中corotuine實現原理是由基類保存函數當前執行位置,每次運行時根據switch判斷要執行的位置,具體可參考boost coroutine 實現原理記錄

一次同步操作是由多個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的數據同步。這里的數據被分成了兩類:

  • 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的同步。

三個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<)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容