您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)如何進行Raft協(xié)議實踐中的SOFAJRaft剖析,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
- SOFAJRaft 概述 -
從通過SOFAJRaft 框架的核心流程剖析加深對Raft協(xié)議的理解。SOFAJRaft 是一個純 Java 的 Raft 算法實現(xiàn)庫, 基于百度 braft 實現(xiàn)而來, 使用 Java 重寫了所有功能, 支持:
領(lǐng)導(dǎo)人選舉和基于優(yōu)先級的半確定性領(lǐng)導(dǎo)人選舉。
日志復(fù)制和恢復(fù)。
快照和日志壓縮。
只讀成員(learner)。
集群成員管理,添加節(jié)點,刪除節(jié)點,替換節(jié)點等。
完全并發(fā)復(fù)制。
容錯能力。
非對稱網(wǎng)絡(luò)分區(qū)容忍性。
當法定人數(shù)同伴都死亡的解決方法。
管道復(fù)制
線性一致讀,ReadIndex/LeaseRead。
額外擴展了一些功能:
對稱網(wǎng)絡(luò)分區(qū)容忍性
重啟后的轉(zhuǎn)移領(lǐng)袖、負載均衡場景實現(xiàn)
更豐富的指標統(tǒng)計展示
通過Jepsen一致性驗證測試
包含嵌入式分布式KV存儲實現(xiàn)
整體項目如下:
- 領(lǐng)袖選舉 -
SOFAJRaft 的選舉主要通過判單兩個屬性:LogIndex 和 Term;Term 即任期,LogIndex即提交到 raft group 中的任務(wù)都將序列化為一條日志存儲下來,每條日志一個編號,在整個 raft group 內(nèi)單調(diào)遞增并復(fù)制到每個 raft 節(jié)點??梢岳斫鉃槭聞?wù)id。投票處理的邏輯主要在 com.alipay.sofa.jraft.core.NodeImpl中,主要有四個函數(shù):
處理處理預(yù)投票請求
Message handlePreVoteRequest(request)
預(yù)投票
void preVote()
處理投票請求
Message handleRequestVoteRequest(request)
投票
electSelf()
整體流程如下:
Candidate(候選人) 被 Election timeout觸發(fā)
Candidate 開始嘗試發(fā)起 pre-vote 預(yù)投票
Follower(追隨者) 判斷是否認可該 pre-vote request
Candidate 根據(jù) pre-vote response 來決定是否發(fā)起 RequestVoteRequest
Follower 判斷是否認可該 RequestVoteRequest
Candidate 根據(jù) response 來判斷自己是否當選
使用預(yù)投票可以防止網(wǎng)絡(luò)抖動等特殊原因引起的瞬時失聯(lián)節(jié)點無故搗亂:候選者在發(fā)起投票之前,先發(fā)起預(yù)投票,如果沒有得到半數(shù)以上節(jié)點的反饋,則候選者就會識趣的放棄參選,也就不會抬升全局的 Term。
投票源碼:
預(yù)投票源碼:
- 存儲機制 -
SOFAJRaft 存儲模塊分為:
Log 存儲記錄 Raft 配置變更和用戶提交任務(wù)日志,把日志從 Leader 復(fù)制到其他節(jié)點上面;
checkAndResolveConflict(entries, done)
offerEvent(done, type)
Disruptor隊列發(fā)布other類型事件
appendToStorage(toAppend)
回調(diào)事件處理器StableClosureEventHandler存儲日志
返回日志里的首/末個日志索引;
按照日志索引獲取 Log Entry 及其任期;
把單個/批量 Log Entry 添加到日志存儲;
從 Log 存儲頭部/末尾刪除日志;
刪除所有現(xiàn)有日志,重置下任日志索引。
LogStorage 是日志存儲實現(xiàn),默認實現(xiàn)基于 RocksDB 存儲,通過 LogStorage 接口擴展自定義日志存儲實現(xiàn);核心接口包括:
LogManager 負責調(diào)用底層日志存儲 LogStorage,針對日志存儲調(diào)用進行緩存、批量提交、必要的檢查和優(yōu)化。
檢查Node節(jié)點,解決日志沖突。
配置管理器:緩存配置變更
LogsInMemory緩存日志Entries
Meta 存儲即元信息存儲記錄 Raft 實現(xiàn)的內(nèi)部狀態(tài),比如當前 term,、投票給哪個節(jié)點等信息
設(shè)置/獲取 Raft 元數(shù)據(jù)的當前任期 Term;
分配/查詢 Raft 元信息的 PeerId 節(jié)點投票。
RaftMetaStorage 元信息存儲實現(xiàn),定義 Raft 元數(shù)據(jù)的 Metadata 存儲模塊核心 API 接口包括:
Snapshot 存儲用于存放用戶的狀態(tài)機 Snapshot 及元信息,用于Node重啟重建整個狀態(tài)機實例。
狀態(tài)機快照 doSnapshot(done)
安裝快照 installSnapshot(request, response, done)。
設(shè)置 filterBeforeCopyRemote ,為 true 表示復(fù)制到遠程之前過濾數(shù)據(jù);
創(chuàng)建快照編寫器;
打開快照閱讀器;
從遠程 Uri 復(fù)制數(shù)據(jù);
啟動從遠程 Uri 復(fù)制數(shù)據(jù)的復(fù)制任務(wù);
配置 SnapshotThrottle,SnapshotThrottle 用于重盤讀/寫場景限流的,比如磁盤讀寫、網(wǎng)絡(luò)帶寬。
SnapshotStorage 用于 snapshot 存儲實現(xiàn),定義 Raft 狀態(tài)機的 Snapshot 存儲模塊核心接口包括:
SnapshotExecutor 用于 snapshot 實際存儲、遠程安裝、復(fù)制的管理。
LogManager 調(diào)用日志存儲 LogStorage 實現(xiàn)邏輯:
SnapshotExecutor 狀態(tài)機快照和遠程安裝鏡像實現(xiàn)邏輯:
- 一致性狀態(tài)機 -
通過存儲的設(shè)計,在引入狀態(tài)機機制,就可以完成一致性狀態(tài)機。SOFAJRaft狀態(tài)機組成有:
StateMachine:業(yè)務(wù)邏輯實現(xiàn)的主要接口,狀態(tài)機運行在每個 raft 節(jié)點上,提交的 task 如果成功,最終都會復(fù)制應(yīng)用到每個節(jié)點的狀態(tài)機上。,核心是 onApply(Iterator) 方法,應(yīng)用通過 Node#apply(task) 提交的日志到業(yè)務(wù)狀態(tài)機。
FSMCaller:封裝對業(yè)務(wù) StateMachine 的狀態(tài)轉(zhuǎn)換的調(diào)用以及日志的寫入等,一個有限狀態(tài)機的實現(xiàn),做必要的檢查、請求合并提交和并發(fā)處理等。
SOFAJRaft Node節(jié)點利用日志復(fù)制完成數(shù)據(jù)同步,主要組成有:
Replicator:用于 leader 向 follower 復(fù)制日志,也就是 raft 中的 appendEntries 調(diào)用,包括心跳存活檢查等。
ReplicatorGroup: 用于單個 RAFT Group 管理所有的 replicator,必要的權(quán)限檢查和派發(fā)。
下面通過簡單介紹了下SOFAJRaft的選舉實現(xiàn)、存儲機制、狀態(tài)機和日志復(fù)制四個方面?;旧贤瓿闪薘aft實現(xiàn)的核心實現(xiàn)。但SOFAJRaft還有更多核心及優(yōu)化,因為篇幅原因沒有進入細細剖析。如果咱們自實現(xiàn)Raft協(xié)議,基本上也是實現(xiàn)這幾個主流程即可完成簡版Raft了。關(guān)于Raft協(xié)議暫時先告一段路,接下去準備開寫ZAB協(xié)議。
看完上述內(nèi)容,你們對如何進行Raft協(xié)議實踐中的SOFAJRaft剖析有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。