天天看點

帶你讀《存儲漫談Ceph原理與實踐》第三章接入層3.2對象存儲RGW(五)

3.2.5   中繼資料/ 資料同步

CephRGW的多資料中心(Multisite)機制用于實作多個 Ceph  對象存儲叢集之間的中繼資料、資料同步。

1.  中繼資料同步

(1)多資料中心簡介

Ceph 的多資料中心有如下幾個概念:Realm、ZoneGroup、Zone,如圖 3-31所示。

帶你讀《存儲漫談Ceph原理與實踐》第三章接入層3.2對象存儲RGW(五)

圖 3-31 多資料中、示意

每個 Realm 都為一個獨立的命名空間,桶名在所在命名空間内是唯一的,即一旦在某個 Realm下建立了桶A,則 A這個名字就被使用了,在該 Realm 下其他人就無法建立出名字為A的桶。

一個 Realm下可以有多個 ZoneGroup。顧名思義,每個ZoneGroup可以對應多個Zone,即 ZoneGroup是一組 Zone的集合,Zone之間同步資料和中繼資料。

通常一個 Zone為多台伺服器組成的一個 Ceph叢集,由一組 RGW 對外提供服務,一個叢集上部署多個 RGW網關,以對請求進行負載均衡。

在一個 Realm下的多個 ZoneGroup中, 必須有一個 MasterZoneGroup,MasterZoneGroup中必須有一個 MasterZone,在 MasterZoneGroup下的 MasterZone中執行使用者的建立、删除、修改操作會記錄一些日志資訊(MDlog),這些日志資訊被克隆到其他 ZoneGroup下的 Zone中,其他Zone中的 RGW網關依照日志資訊從 MasterZoneGroup 下的 MasterZone 中已配置的 endpoints 拉取中繼資料資訊并執行相應操作。

在 Ceph的配置中有以下幾個參數與多資料中心機制相關,分别為 rgw_realm、rgw_zonegroup、rgw_zone。一旦設定好這 3 個參數并啟動 RGW網關,RGW就會預設到.rgw.root下尋找相應的 Realm、ZoneGroup、Zone 資訊,如果無法找到則啟動失敗。使用者也可以通過修改參數rgw_realm_root_pool、rgw_zonegroup_root_pool、rgw_zone_root_pool 的配置值,來告訴RGW網關到指定的存儲池下讀取 Realm、ZoneGroup、Zone 等資訊。預設情況下,一個Realm下的不同ZoneGroup之間隻會進行中繼資料同步,中繼資料包括

使用者資訊、bucket、bucket.instance資訊。RGW執行個體在啟動時,會啟動 RGWMetaSync-

ProcessorThread 線程進行多資料中心中繼資料的同步服務。

一個新的ZoneGroup加入已存在的Realm 時,會執行全量同步,完成全量同步後就會進入增量同步階段。在此階段,新加入的 ZoneGroup下的Zone内的 RGW網關每隔 20s

(通過 INCREMENTAL_INTERVAL參數配置)到 MasterZoneGroup中拉取日志資訊MDlog。在增量同步階段,每隔 20s執行如下動作。

1)  查詢請求帶上 marker參數發送到MasterZoneGroup,查詢是否有新增的MDlog,如果有,則拉取新增的MDlog到本地叢集;

2)  讀取儲存在本叢集的新增的 MDlog并處理,按照 MDlog記錄資訊發送讀取中繼資料請求到 MasterZoneGroup;

3)儲存從 MasterZoneGroup 讀取到的中繼資料資訊到本地叢集;4)更新 marker參數。

(2) MDLog簡介

Mdlog為 MasterZoneGroup上的RGW網關記錄, 日志資訊記錄在 Log池下的meta.log.PERIOD.SHARD_ID對象的 OMAP上,shard_id預設為 0~31。

以下指令可查詢第 0個 shard上的 omapkey,key為 1_開頭,後面帶記錄 Log的時間戳。

#rados -p zgp2-z1.rgw.log listomapkeys meta.log.315d0473-9ff8-4828-83fd-96fdc36ed618.01_1598684563.695864_0.1

也可以使用radosgw-admin指令檢視MDlog日志資訊的狀态,狀态資訊中有marker和 last_update的時間資訊,marker記錄上次同步的位置,last_update記錄上次同步的時間。

#radosgw-admin mdlog status[

{

"marker": "1_1598768113.971442_11.1""last_update":"2020-08-3006:15:13.971442Z"

}

]

status資訊儲存在 Log池下的 RADOS 對象中,可通過如下指令進行查詢。

#rados -p zgp2-z1.rgw.log lsmdlog.sync-status.shard.0mdlog.sync-status

當主資料中心沒有中繼資料更新記錄到MDlog時,以下是從主資料中心拉取 MDlog請求時沒有新 MDlog傳回的請求和響應。

GET/admin/log?type=metadata&id=0&period=315d0473-9ff8-4828-83fd-

96fdc36ed618&max-entries=100&marker=目前的 marker&rgwx-zonegroup=7085627f-27f8-

4779-9552-ebdd13c265e2HTTP/1.1

HTTP/1.1200 OK

Content-Length:44

"marker":""

"entries": []"truncated":false

當主資料中心有中繼資料更新記錄到MDlog時,以下是從主資料中心拉取 MDlog請求時有新 MDlog傳回的請求和響應。

96fdc36ed618&max-entries=100&marker= 目前的marker&rgwx-zonegroup=7085627f-27f8-

Content-Length:598

"marker":"1_1598774754.303770_13.1"

"entries":[

...

"timestamp":"2020-08-3008:05:54.234410256Z"

"section":"user"

"data": {

"status": {

"status":"write"

如果從主資料中心拉取 MDlog請求時有新的 MDlog傳回,發起拉取請求的 RGW則進入 MDlog的處理流程,即發送新的擷取中繼資料請求到 MasterZoneGroup去拉取新的資訊覆寫本地舊的中繼資料資訊。如下為在MasterZoneGroup中建立一個使用者後,非MasterZoneGroup向 MasterZoneGroup的網關發起的拉取使用者資訊的請求。

GET/admin/metadata/user/user001?key=user001&rgwx-zonegroup=abcHTTP/1.1

Content-Length:713

"default_storage_class": """keys": [

"access_key":""

"secret_key":""

"user":"user001"

拉取到新的使用者資訊寫入本地叢集後,更新marker參數,這樣在下一個20s時帶上該 Marker參數,就會隻傳回本Zone沒有的 MDlog,對處理過的 MDlog就不會傳回,進而實作了中繼資料的增量更新。

RGW 程序隻有同時滿足如下條件,才會進行MDlog的記錄。

◆  rgw_zonegroup為 MasterZoneGroup。

◆  目前的ZoneGroup内的Zone個數多于1個或者目前Realm下的ZoneGroup多于1個。

(3)  示例:非主資料中心建立桶

使用者資訊在 MasterZoneGroup中建立後通過MDlog的方式同步到其他 ZoneGroup下所有的 Zone中,例如非 MasterZoneGroup下的某個RGW 網關接收到建立桶的請求,該 RGW網關會将請求轉發到 MasterZoneGroup的網關處理。

voidRGWCreateBucket::execute()

if (!store->svc.zone->is_meta_master()) {JSONParserjp;

op_ret=forward_request_to_master(s NULLstore in_data&jp);

如果主資料中心建立失敗(例如主資料中心沒有該使用者,該使用者在非MasterZoneGroup中建立),則建立桶失敗。是以所有使用者必須在MasterZoneGroup中建立,并通過 MDlog同步到其他資料中心,使用者的修改和删除也必須在 MasterZoneGroup中執行。如果 MasterZoneGroup成功傳回轉發建立桶的請求,則繼續執行剩餘的建立桶流程,将 bucketinfo儲存到本資料中心的RADOS。MasterZoneGroup接收到該建立桶的請求後,其下的RGW也會執行 RGWCreateBucket::execute()。由于它是主資料中心,同時也會記錄 MDlog,在中繼資料同步線程中 MDlog會克隆到其他ZoneGroup,所有的ZoneGroup下都會儲存該 bucketinfo資訊,例如 MasterZoneGroup為 beijing1,建立桶的請求發到ZoneGroup為beijing2的 RGW網關,這個請求會被beijing2 的RGW網關轉發到 beijng1的RGW網關,同時 MDlog資訊會被同步到beijing2、guangzhou1、hunan1等所有 ZoneGroup。在建立好桶之後,如果向這個桶上傳資料,則需要将上傳資料請求發到ZoneGroup為beijing2的 RGW網關。如果上傳請求發到ZoneGroup 為guangzhou1的 RGW網關,guangzhou1的 RGW網關會傳回301 狀态碼,表明請求所通路的桶不在本資料中心。

對于其他桶的中繼資料操作,大部分的請求會被轉發到MasterZoneGroup,例如删除桶、設定桶的靜态網站、設定桶的多版本控制、設定桶的桶政策、設定桶的   ACL、設定桶的生命周期規則、設定桶的跨域通路配置等。

2.  資料同步

Ceph 的資料同步是指在多資料中心不同Zone 之間同步使用者上傳的檔案資料。

可以将實體資料的同步分為 3 個部分:記錄日志、資料更新通知以及資料更新。下面分别介紹。

(1)記錄日志

在對資料進行操作時(比如上傳、删除等操作),RGW會記錄一些日志資訊,為之後的實體資料同步服務。日志主要分兩部分。

◆ bucketindexlog:在更新 bucketindex、設定 olh(objectlogicalhead,對象邏輯頭)時會記錄該日志,包含了對象、操作類型等資訊;

◆  datalog:記錄發生變化的 bucketshard 等資訊。

在進行同步時,依據 datalog,可以知道哪些 bucketshard 發生了資料的變化。而通過bucketindexlog,則可以對對應的對象進行操作。比如,indexlog中記錄的是add操作,就會從 SourceZone 擷取具體的對象,如果是 remove 操作,就會把相應的對象删除。

(2)資料更新通知

與中繼資料同步類似,實體資料的同步同樣擁有一個線程周期性地進行資料更新通知。

◆  初始化

實體資料的更新通知由 RGWDataNotifier線程負責。它的初始化以及啟動都是在RGWRados的初始化函數中。

data_notifier = new RGWDataNotifier(this);data_notifier->start();

◆  運作

在被啟動之後,每隔一段時間(由 rgw_md_notify_interval_msec配置,預設 200ms)

會進行資料更新通知,将記錄在datalog中發生變化的 shard發送到其他 Zone。其他Zone在接收到更新通知後,會喚醒相應的資料同步線程。

(3)資料更新

為了與不同的 Zone進行實體資料的同步,RGW 會啟動單獨的同步線程。

資料同步線程的初始化,同樣在 RGW 的初始化中,資料同步線程可能會有多個。對于需要進行資料同步的Zone,都會啟動一個線程來專門負責從該Zone 擷取同步資料。

同步線程啟動之後,會開始調用 RGWDataSyncProcessorThread的 process來對資料進行處理,其主要流程如下。

1)  從 RADOS中讀取 datasyncstatus,以及各個 Logshard的 syncmarker。如果是第一次同步,RADOS 中還不存在這些資訊,會先對 status 進行初始化。

2)  datasyncstatus共 有 3種 狀 态, 即 StateInit、StateBuildingFullSyncMaps、StateSync。依據狀态的不同,會執行不同的操作。

a)StateInit:該狀态下,會執行一些同步的初始化操作,例如,往LogPool 中寫入sync_status對象,從遠端擷取各個 Logshard的 syncmarker寫入LogPool,将 sync_status設定為 StateBuildingFullSyncMaps等。

b)StateBuildingFullSyncMaps:該狀态下,會從遠端擷取所有的 bucket 資訊。之後,會以 bucket  shard為機關,将所有需要同步的bucketshard寫入 OMAP中,并更新 Logshard的同步 marker,最後将狀态置為StateSync。

c)StateSync:該狀态即為正常的同步狀态,在進行同步時,以 Logshard為機關,對每一個 Logshard進行資料同步操作。

3)  在對某個 Logshard進行資料同步時,依據Logshard的 syncmarker來判斷執行全量還是增量同步。同樣,在執行過一次全量同步後,之後執行的就是增量同步了。

4)  在每一個 Logshard中,包含了多個條目,每一個條目是一個bucketshard資訊。對 Logshard的同步,實際上就是周遊并同步這些bucketshard。

5) 同步 bucketshard過程中有不同的狀态。依據不同的狀态,來依次執行初始化、全量同步以及增量同步。同樣,初始化與全量同步隻會執行一次,之後便是增量同步。為   了同步 bucketshard,RGW會從對端Zone的RGW擷取該bucketshard的bucketindexlog,并依據這些 Log,最終決定是從遠端擷取實體對象,還是從本地删除對象,或者進行其他的操作,此時才會涉及真正的實體資料的操作。

(4)删除日志

如果不删除日志,則随着時間的增加,日志會越來越大。是以,RGW每隔一段時間都會删除已經同步完成的資料日志。間隔時間由rgw_sync_log_trim_interval确定,預設是1200s。在進行日志删除時,需要從各個 Zone擷取資料同步狀态資訊,并根據這些資訊, 判斷出哪些日志已經被同步完成了,并将其從RADOS中删除。

(5)總結

從實體資料同步過程中可以看到涉及多種同步狀态的判斷。之是以有這麼多的狀态,   是因為 RGW 在進行資料同步時,将其在邏輯上分成了多個層級。我們可以将同步的層級分成如下4個層次。

1)Zone級别

該層級表示了與某個 Zone 的同步狀态,表征該層級的同步狀态由下面的結構給出。

struct rgw_data_sync_info {enum SyncState {StateInit = 0

StateBuildingFullSyncMaps=1

StateSync = 2

};

uint16_t state;uint32_tnum_shards;

rgw_data_sync_info():state((int)StateInit)num_shards(0){}

2)Logshard級别

記錄資料變化時會将日志分成多個   Log,進而在資料量較大時,獲得較好的性能。下面是表示 Logshard層級的同步狀态結構。

struct rgw_data_sync_marker {enum SyncState {

FullSync = 0

IncrementalSync= 1

uint16_t state;stringmarker;

string next_step_marker;uint64_t total_entries;uint64_tpos;

real_timetimestamp;

rgw_data_sync_marker():state(FullSync)total_entries(0)pos(0){}

3)bucketshard級别

預設情況下,bucketshard大小為 0。但為了讓單個容器可以承載更多的對象,不得不以犧牲 list對象的性能為代價,增大bucketshard的值。目前線上上環境中,該值通常都不配置為 0。是以,我們可以認為,每個bucket實際上都存在多個 shard,各自承載着部分對象。而在同步過程中,每一個 bucketshard都歸屬于某個 Logshard。對于logshard的同步,實際上就是對其下的各個 bucketshard進行同步。

4)對象級别

在每一個 bucketshard中都儲存了很多對象, 同步 bucketshard,就是同步其下面的這些對象。該層級涉及對實體資料的操作,并且也是同步過程中的最底層(不考慮RADOS),沒有專門的結構來儲存同步資訊。

3.  小結

因為 Multisite是一個Zone層面的功能處理機制,是以預設情況下是 Zone級的資料同步,即配置了Multisite之後,整個 Zone中的資料都會被同步處理。

整個Zone 層面的資料同步,操作粒度過于粗糙,在很多場景下都是非常不适用的。目前,CephRGW還支援通過bucketsyncenable/disable來啟用/禁用存儲桶級的資料同步,操作粒度更細,靈活度也更高。