您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關基于raft協議的RocketMQ DLedger多副本日志復制設計原理是怎樣的,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
小編將首先梳理一下 RocketMQ DLedger 多副本關于日志復制的三個核心流程圖,然后再思考一下在異常情況下如何保證數據一致性。
接下來我們來探討日志復制的核心設計要點。
為了方便對日志進行管理與辨別,raft 協議為一條一條的消息進行編號,每一條消息達到主節點時會生成一個全局唯一的遞增號,這樣可以根據日志序號來快速的判斷數據在主從復制過程中數據是否一致,在 DLedger 的實現中對應 DLedgerMemoryStore 中的 ledgerBeginIndex、ledgerEndIndex,分別表示當前節點最小的日志序號與最大的日志序號,下一條日志的序號為 ledgerEndIndex + 1 。
與日志序號還與一個概念綁定的比較緊密,即當前的投票輪次。
請思考如下問題,Leader 節點收到客戶端的數據寫入請求后,通過解析請求,提取數據部分,構建日志對象,并生成日志序號,用 seq 表示,然后存儲到 Leader 節點中,然后將日志廣播(推送)到其從節點,由于這個過程中存在網絡時延,如果此時客戶端向主節點查詢 seq 的日志,由于日志已經存儲在 Leader 節點中了,如果直接返回給客戶端顯然是有問題的,那該如何來避免這種情況的發生呢?
為了解決上述問題,DLedger 的實現(應該也是 raft 協議的一部分)引入了已提交指針(committedIndex)。即當主節點收到客戶端請求時,首先先將數據存儲,但此時數據是未提交的,此過程可以稱之為追加,此時客戶端無法訪問,只有當集群內超過半數的節點都將日志追加完成后,才會更新 committedIndex 指針,只有已提交的數據才能被客戶端訪問。
一條日志要能被提交的充分必要條件是日志得到了集群內超過半數節點成功追加,才能被認為已提交。
從上文得知,一個擁有3個節點的 DLedger 集群,只要主節點和其中一個從節點成功追加日志,則認為已提交,客戶端即可通過主節點訪問。由于部分數據存在延遲,在 DLedger 的實現中,讀寫請求都將由 Leader 節點來負責。那落后的從節點如何再次跟上集群的步驟呢?
要重新跟上主節點的日志記錄,首先要知道的是如何判斷從節點已丟失數據呢?
DLedger 的實現思路是,DLedger 會按照日志序號向從節點源源不斷的轉發日志,從節點接收后將這些待追加的數據放入一個待寫隊列中。關鍵中的關鍵:從節點并不是從掛起隊列中處理一個一個的追加請求,而是首先查閱從節點當前已追加的最大日志序號,用 ledgerEndIndex 表示,然后嘗試追加 (ledgerEndIndex + 1)的日志,用該序號從代寫隊列中查找,如果該隊列不為空,并且沒有 (ledgerEndIndex + 1)的日志條目,說明從節點未接收到這條日志,發生了數據缺失。然后從節點在響應主節點 append 的請求時會告知數據不一致,然后主節點的日志轉發線程其狀態會變更為COMPARE,將向該從節點發送COMPARE命令,用來比較主從節點的數據差異,根據比較的差異重新從主節點同步數據或刪除從節點上多余的數據,最終達到一致。于此同時,主節點也會對PUSH超時推送的消息發起重推,盡最大可能幫助從節點及時更新到主節點的數據。
關于基于raft協議的RocketMQ DLedger多副本日志復制設計原理是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。