您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何用Nacos實(shí)現(xiàn)Raft算法”,在日常操作中,相信很多人在如何用Nacos實(shí)現(xiàn)Raft算法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”如何用Nacos實(shí)現(xiàn)Raft算法”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
導(dǎo)讀 | 為了提高理解性,Raft 將一致性算法分為了幾個(gè)部分,包括領(lǐng)導(dǎo)選取(leader selection)、日志復(fù)制(log replication)、安全(safety),并且使用了更強(qiáng)的一致性來減少了必須需要考慮的狀態(tài)。 |
快速了解Raft算法
Raft 適用于一個(gè)管理日志一致性的協(xié)議,相比于 Paxos 協(xié)議 Raft 更易于理解和去實(shí)現(xiàn)它。為了提高理解性,Raft 將一致性算法分為了幾個(gè)部分,包括領(lǐng)導(dǎo)選取(leader selection)、日志復(fù)制(log replication)、安全(safety),并且使用了更強(qiáng)的一致性來減少了必須需要考慮的狀態(tài)。
相比Paxos,Raft算法理解起來更加直觀。
Raft算法將Server劃分為3種狀態(tài),或者也可以稱作角色:
Leader:負(fù)責(zé)Client交互和log復(fù)制,同一時(shí)刻系統(tǒng)中最多存在1個(gè)。
Follower:被動(dòng)響應(yīng)請(qǐng)求RPC,從不主動(dòng)發(fā)起請(qǐng)求RPC。
Candidate:一種臨時(shí)的角色,只存在于leader的選舉階段,某個(gè)節(jié)點(diǎn)想要變成leader,那么就發(fā)起投票請(qǐng)求,同時(shí)自己變成candidate。如果選舉成功,則變?yōu)閏andidate,否則退回為follower
狀態(tài)或者說角色的流轉(zhuǎn)如下:
在Raft中,問題分解為:領(lǐng)導(dǎo)選取、日志復(fù)制、安全和成員變化。
復(fù)制狀態(tài)機(jī)通過復(fù)制日志來實(shí)現(xiàn):
日志:每臺(tái)機(jī)器保存一份日志,日志來自于客戶端的請(qǐng)求,包含一系列的 命令
狀態(tài)機(jī):狀態(tài)機(jī)會(huì)按順序執(zhí)行這些 命令
一致性模型:分布式環(huán)境下,保證多機(jī)的日志是一致的,這樣回放到狀態(tài)機(jī)中的狀態(tài)是一致的
Raft算法選主流程
Raft中有Term的概念,Term類比中國歷史上的朝代更替,Raft 算法將時(shí)間劃分成為任意不同長度的任期(term)。
選舉流程
follower增加當(dāng)前的term,轉(zhuǎn)變?yōu)閏andidate。
candidate投票給自己,并發(fā)送RequestVote RPC給集群中的其他服務(wù)器。
收到RequestVote的服務(wù)器,在同一term中只會(huì)按照先到先得投票給至多一個(gè)candidate。且只會(huì)投票給log至少和自身一樣新的candidate。
Nacos中的CP一致性
Spring Cloud Alibaba Nacos 在 1.0.0 正式支持 AP 和 CP 兩種一致性協(xié)議,其中的CP一致性協(xié)議實(shí)現(xiàn),是基于簡化的 Raft 的 CP 一致性。
如何實(shí)現(xiàn)Raft算法
Nacos server在啟動(dòng)時(shí),會(huì)通過RunningConfig.onApplicationEvent()方法調(diào)用RaftCore.init()方法。
啟動(dòng)選舉
public static void init() throws Exception { Loggers.RAFT.info("initializing Raft sub-system"); // 啟動(dòng)Notifier,輪詢Datums,通知RaftListener executor.submit(notifier); // 獲取Raft集群節(jié)點(diǎn),更新到PeerSet中 peers.add(NamingProxy.getServers()); long start = System.currentTimeMillis(); // 從磁盤加載Datum和term數(shù)據(jù)進(jìn)行數(shù)據(jù)恢復(fù) RaftStore.load(); Loggers.RAFT.info("cache loaded, peer count: {}, datum count: {}, current term: {}", peers.size(), datums.size(), peers.getTerm()); while (true) { if (notifier.tasks.size() <= 0) { break; } Thread.sleep(1000L); System.out.println(notifier.tasks.size()); } Loggers.RAFT.info("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start)); GlobalExecutor.register(new MasterElection()); // Leader選舉 GlobalExecutor.register1(new HeartBeat()); // Raft心跳 GlobalExecutor.register(new AddressServerUpdater(), GlobalExecutor.ADDRESS_SERVER_UPDATE_INTERVAL_MS); if (peers.size() > 0) { if (lock.tryLock(INIT_LOCK_TIME_SECONDS, TimeUnit.SECONDS)) { initialized = true; lock.unlock(); } } else { throw new Exception("peers is empty."); } Loggers.RAFT.info("timer started: leader timeout ms: {}, heart-beat timeout ms: {}", GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS); }
在init方法主要做了如下幾件事:
獲取Raft集群節(jié)點(diǎn) peers.add(NamingProxy.getServers()); Raft集群數(shù)據(jù)恢復(fù) RaftStore.load(); Raft選舉 GlobalExecutor.register(new MasterElection()); Raft心跳 GlobalExecutor.register(new HeartBeat()); Raft發(fā)布內(nèi)容 Raft保證內(nèi)容一致性
選舉流程
其中,raft集群內(nèi)部節(jié)點(diǎn)間是通過暴露的Restful接口,代碼在 RaftController 中。RaftController控制器是raft集群內(nèi)部節(jié)點(diǎn)間通信使用的,具體的信息如下:
POST HTTP://{ip:port}/v1/ns/raft/vote : 進(jìn)行投票請(qǐng)求 POST HTTP://{ip:port}/v1/ns/raft/beat : Leader向Follower發(fā)送心跳信息 GET HTTP://{ip:port}/v1/ns/raft/peer : 獲取該節(jié)點(diǎn)的RaftPeer信息 PUT HTTP://{ip:port}/v1/ns/raft/datum/reload : 重新加載某日志信息 POST HTTP://{ip:port}/v1/ns/raft/datum : Leader接收傳來的數(shù)據(jù)并存入 DELETE HTTP://{ip:port}/v1/ns/raft/datum : Leader接收傳來的數(shù)據(jù)刪除操作 GET HTTP://{ip:port}/v1/ns/raft/datum : 獲取該節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)信息 GET HTTP://{ip:port}/v1/ns/raft/state : 獲取該節(jié)點(diǎn)的狀態(tài)信息{UP or DOWN} POST HTTP://{ip:port}/v1/ns/raft/datum/commit : Follower節(jié)點(diǎn)接收Leader傳來得到數(shù)據(jù)存入操作 DELETE HTTP://{ip:port}/v1/ns/raft/datum : Follower節(jié)點(diǎn)接收Leader傳來的數(shù)據(jù)刪除操作 GET HTTP://{ip:port}/v1/ns/raft/leader : 獲取當(dāng)前集群的Leader節(jié)點(diǎn)信息 GET HTTP://{ip:port}/v1/ns/raft/listeners : 獲取當(dāng)前Raft集群的所有事件監(jiān)聽者 RaftPeerSet
心跳機(jī)制
Raft中使用心跳機(jī)制來觸發(fā)leader選舉。心跳定時(shí)任務(wù)是在GlobalExecutor 中,通過 GlobalExecutor.register(new HeartBeat())注冊(cè)心跳定時(shí)任務(wù),具體操作包括:
重置Leader節(jié)點(diǎn)的heart timeout、election timeout;
sendBeat()發(fā)送心跳包 public class HeartBeat implements Runnable { @Override public void run() { try { if (!peers.isReady()) { return; } RaftPeer local = peers.local(); local.heartbeatDueMs -= GlobalExecutor.TICK_PERIOD_MS; if (local.heartbeatDueMs > 0) { return; } local.resetHeartbeatDue(); sendBeat(); } catch (Exception e) { Loggers.RAFT.warn("[RAFT] error while sending beat {}", e); } } }
簡單說明了下Nacos中的Raft一致性實(shí)現(xiàn),更詳細(xì)的流程,可以下載源碼,查看 RaftCore 進(jìn)行了解。源碼可以通過以下地址檢出:
git clone https://github.com/alibaba/nacos.git
到此,關(guān)于“如何用Nacos實(shí)現(xiàn)Raft算法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。