溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何用Nacos實(shí)現(xiàn)Raft算法

發(fā)布時(shí)間:2021-12-31 17:12:04 來源:億速云 閱讀:275 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“如何用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)如下:

如何用Nacos實(shí)現(xiàn)Raft算法

在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)。

如何用Nacos實(shí)現(xiàn)Raft算法

選舉流程

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

如何用Nacos實(shí)現(xiàn)Raft算法

到此,關(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í)用的文章!

向AI問一下細(xì)節(jié)

免責(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)容。

AI