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