【osd】Ceph中的数据一致性
流程細化
寫流程:以 FileStore 后端存儲為例
1)client把寫請求發到Primary OSD上,Primary OSD上將寫請求序列化到一個事務中(在內存里),然后構造一條pglog記錄,也序列化到這個事務中,然后將這個事務以directIO的方式異步寫入journal,同時Primary OSD把寫請求和pglog(pglog_entry是由primary生成)發送到Replicas上;
2)在Primary OSD將事務寫到journal上后,會通過一系列的線程和回調處理,然后將這個事務里的數據寫入filesystem(只是寫到文件系統的緩存里,會有線程定期刷數據),這個事務里的pglog記錄(也包括pginfo的last_complete和last_update)會寫到leveldb,還有一些擴展屬性相關的也在這個事務里,在遍歷這個事務時也會寫到leveldb;
3)在Replicas上,也是進行類似于Primary的動作,先寫journal,寫成功會給Primary發送一個committed ack,然后將這個事務里的數據寫到filesystem,pglog與pginfo寫到leveldb里,寫完后會給Primary發送另外一個applied ack;
4)Primary在自己完成journal的寫入時,以及在收到Replica的committed ack時都會檢查是否多個副本都寫入journal成功了,如果是則向client端發送ack通知寫完成;Primary在自己完成事務寫到文件系統和leveldb后,以及在收到replica的applied ack時都會檢查是否多個副本都寫文件系統成功,如果是則向client端發送ack通知數據可讀;
讀流程:由于實現了強一致性,主節點和從節點的數據基本完全一致,故在讀取時采用了隨機的方式進行OSD的選取,然后讀取對應的數據。
PGLog封裝到transaction里面和journal一起寫到盤上的好處:如果osd異常崩潰時,journal寫完成了,但是數據有可能沒有寫到磁盤上,相應的pg log也沒有寫到leveldb里,這樣在osd再啟動起來時,就會進行journal replay,這樣從journal里就能讀出完整的transaction,然后再進行事務的處理,也就是將數據寫到盤上,pglog寫到leveldb里。
1)正常情況下,都是由Primary處理client端的I/O請求,這時,Primary和Replicas上的last_update和last_complete都會指向pglog最新記錄;
2)當Primary掛掉后,會選出一個Replica作為“臨時主”,這個“臨時主”負責處理新的讀寫請求,并且這個時候“臨時主”和剩下的Replicas上的last_complete和last_update都更新到該副本上的pglog的最新記錄;
3)當原來的Primary又重啟時,會從本地讀出pginfo和pglog,當發現last_complete<last_update時,last_complete和last_update之間就可能存在丟失的對象,遍歷last_complete到last_update之間的pglog記錄,對于每一條記錄,從本地讀出該記錄里對象的屬性(包含本地持久化過的版本),對比pglog記錄里的對象版本與讀出來的版本,如果讀出來的對象版本小于pglog記錄里的版本,說明該對象不是最新的,需要進行恢復,因此將該對象加到missing列表里;
4)Primary發起peering過程,即“搶回原來的主”,選出權威日志,一般就是“臨時主”的pglog,將該權威日志獲取過來,與自己的pglog進行merge_log的步驟,構建出missing列表,并且更新自己的last_update為最新的pglog記錄(與各個副本一致),這個時候last_complete與last_update之間的就會加到missing列表,并且peering完成后會持久化last_complete和last_update;
5)當有新的寫入時,仍然是由Primary負責處理,會更新last_update,副本上會同時更新last_complete,與此同時,Primary會進行恢復,就是從其他副本上拉取對象數據到自己這里進行恢復,每當恢復完一個時,就會更新自己的last_complete(會持久化的),當所有對象都恢復完成后,last_complete就會追上last_update了。
6)當恢復過程中,Primary又掛了再起來恢復時,先讀出本地pglog時就會根據自己的last_complete和last_update構建出missing列表,而在peering的時候對比權威日志和本地的pglog發現權威與自己的last_update都一樣,peering的過程中就沒有新的對象加到missing列表里,總的來說,missing列表就是由兩個地方進行構建的:一個是osd啟動的時候read_log里構建的,另一個是peering的時候對比權威日志構建的;
Replica 故障恢復
與Primary的恢復類似,peering都是由Primary發起的,Replica起來后也會根據pglog的last_complete和last_update構建出replica自己的missing,然后Primary進行peering的時候對比權威日志(即自身)與故障replica的日志,結合replica的missing,構建出peer_missing,然后就遍歷peer_missing來恢復對象。然后新的寫入時會在各個副本上更新last_complete和last_update,其中故障replica上只更新last_update,恢復過程中,每恢復完一個對象,故障replica會更新last_complete,這樣所有對象都恢復完成后,replica的last_complete就會追上last_update。
如果恢復過程中,故障replica又掛掉,然后重啟后進行恢復的時候,也是先讀出本地log,對比last_complete與last_update之間的pglog記錄里的對象版本與本地讀出來的該對象版本,如果本地不是最新的,就會加到missing列表里,然后Primary發起peering的時候發現replica的last_update是最新的,peering過程就沒有新的對象加到peer_missing列表里,peer_missing里就是replica自己的missing里的對象。
參考資料
1.Ceph中的數據一致性
總結
以上是生活随笔為你收集整理的【osd】Ceph中的数据一致性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win10升级预览版9926出现0x80
- 下一篇: crunch使用方法_launch中文