1. 程式人生 > >RocketMQ 多副本前置篇:初探raft協議

RocketMQ 多副本前置篇:初探raft協議

目錄

  • 1、Leader選舉
    • 1.1 一輪投票中,只有一個節點發起投票的情況
    • 1.2 一輪投票中,超過一個節點發起投票的情況
    • 1.3 思考如何實現Raft選主
  • 2、日誌複製

Raft協議是分散式領域解決一致性的又一著名協議,主要包含Leader選舉、日誌複製兩個部分。

溫馨提示:
本文根據raft官方給出的raft動畫進行學習,其動畫展示地址:http://thesecretlivesofdata.com/raft/

@(本節目錄)

1、Leader選舉

1.1 一輪投票中,只有一個節點發起投票的情況


Raft協議中節點有3種狀態(角色):

  • Follower
    跟隨者。
  • Candidate
    候選者。
  • Leader
    領導者(Leader),通常我們所說的的主節點。

首先3個節點初始狀態為 Follower,每個節點會有一個超時時間(計時器),其時間設定為150ms~300ms之間的隨機值。當計時器到期後,節點狀態從 Follower 變成 Candidate,如下圖所示:

通常情況下,三個節點中會有一個節點的計時器率先到期,節點狀態變為 Candidate ,候選者狀態下的節點會發起選舉投票。我們先來考慮只有一個節點變為Candidate時是如何進行選主的。

當節點狀態為Candidate,將發起一輪投票,由於是第一輪投票,設定本輪投票輪次為1,並首先為自己投上一票,正如上圖所示的NodeA節點,Team為1,Vote Count為1.

當一個節點的定時器超時後,首先為自己投上一票,然後向該組內其他的節點發起投票(用拉票更加合適),傳送投票請求。

當叢集內的節點收到投票請求外,如果本輪未進行過投票,則贊同,否則反對,然後將結果返回,並重置計時器。

當節點A收到的贊同票大於一半時,則升級為該叢集的 Leader,然後定時向叢集內的其他節點發送心跳,以便確定自己的領導地位,正如下圖所示。

Node A,叢集中的 Leader正在向其他節點發送心跳包。


節點在收到 Leader 的心跳包後,返回響應結果,並重置自身的計時器,如果 Flower 狀態的節點在計時時間超時內沒有收到Leader 的心跳包,就會從 Flower 節點變成 Candidate,該節點就會發起下一輪投票。

例如NodeA節點宕機,停止向它的從傳送心跳,我們來看一下叢集如何重新選主。

如果主節點宕機,則停止向叢集內的節點發送心跳包。隨著計時器的到期,節點B的先於節點C變成 Candidate,則節點B向叢集內的其他節點發起投票,如下圖所示。

節點B,首先將投票輪次設定為2,然後首先為自己投上一篇,然後向其他節點發起投票請求。

節點C收到請求,由於其投票輪次大於自己的投票輪次,並該輪次並未投票,投出贊成票並返回結果,然後重置計時器。節點B將順理成章的成為新的Leader並定時傳送心跳包。

3個節點的選主就介紹到這裡了,也許有網友會說,雖然各個節點的計時器是隨機的,但也有可能同一時間,或一個節點在未收到另一個節點發起的投票請求之前變成 Candidate,即在一輪投票過程中,有大於1個的節點狀態都是 Candidate,那該如何選主呢?

下面以4個節點的叢集為例,來闡述上述這種情況情況下,如何進行選主。

1.2 一輪投票中,超過一個節點發起投票的情況

首先同時有兩個節點進入Candidate狀態,並開始新的一輪投票,當前投票編號為4,首先先為自己投上一票,然後向叢集中的其他節點發起投票,如下圖所示:

然後各個節點收到投票請求,如下所示,進行投票:

首先節點C、D在收到D、C節點的投票請求時,都會返回不同意,因為在本輪投票中,已經各自為自己投了一票,按照上圖,節點A同意C節點、節點B同意D節點,那此時C、D都只獲的兩票,當然如果A,B都認為C或D成為主節點,則選擇就可以結束了,上圖顯示,C、D都只獲的2票,未超過半數,無法成為主節點,那接下來會發生什麼呢?請看下圖:

此時A,B,C,D的定時器各自在倒計時,當節點成為Candidate時,或自身狀態本身是Candidate並且定時器觸發後,發起一輪新的投票,圖中是節點B、節點D同時發起了新的一輪投票。

投票結果如下:節點A,節點C同意節點B成為leader,但由於BD都發起了第5輪投票,最終的投票輪次更新為6,如圖所示:

關於Raft協議的選主就介紹到這裡了,接下來我們來思考一下,如果自己實現 Raf t協議,至少要考慮哪些問題,為下一篇原始碼閱讀Dleger(RocketMQ多副本)模組提供一些思路。

1.3 思考如何實現Raft選主

  1. 節點狀態
    需要引入3中節點狀態:Follower(跟隨者)、Candidate(候選者),投票的觸發點,Leader(主節點)。
  2. 進入投票狀態的計時器
    Follower、Candidate 兩個狀態時,需要維護一個計時器,每次定時時間從150ms-300ms之間進行隨機,即每個節點的每次的計時過期不一樣,Follower狀態時,計時器到點後,觸發一輪投票。節點在收到投票請求、Leader 的心跳請求並作出響應後需要重置定時器。
  3. 投票輪次Team
    Candidate 狀態的節點,每發起一輪投票,Term 加一;Term的儲存。
  4. 投票機制
    每一輪一個節點只能為一個節點投贊成票,例如節點A中維護的輪次為3,並且已經為節點B投了贊成票,如果收到其他節點,投票輪次為3,則會投反對票,如果收到輪次為4的節點,是又可以投贊成票的。
  5. 成為Leader的條件
    必須得到叢集中節點的大多數,即超過半數,例如如果叢集中有3個節點,則必須得到兩票,如果其中一臺伺服器宕機,剩下的兩個節點,還能進行選主嗎?答案是可以的,因為可以得到2票,超過初始叢集中3的一半,所以通常叢集中的機器各位儘量為計數,因為4臺的可用性與3臺的一樣。

溫馨提示:上述結論只是我的一些思考,我們可以帶著上述思考,進入到Dleger的學習中,下一篇將從原始碼分析的角度來學習大神是如何實現Raft協議的Leader選主的,讓我們一起期待吧。

2、日誌複製

完成叢集內的選主工作後,客戶端向主節點發送請求,由主節點負責資料的複製,使叢集內的資料保持一致性,初始狀態如下圖所示:

客戶端向主節點發起請求,例如set 5,將資料更新為5,如下圖所示:

主節點收到客戶端請求後,將資料追加到Leader的日誌中(但未提交),然後在下一個心跳包中將日誌轉發到叢集內從節點,如下圖所示:

從節點收到Leader的日誌後,追加到從節點的日誌檔案中,並返回確認ACK。Leader收到從節點的確認資訊後,向客戶端傳送確認資訊。

上述的日誌複製比較簡單,是由於只考慮正常的情況,如果中間發生異常,該如何保證資料一致性呢?

  1. 如果 Leader 節點向從節點廣播日誌時,其中某個從節點發送故障宕機,該如何處理呢?
  2. 日誌在什麼環節進行提交呢?Leader節點在收到客戶端的資料變更請求後,首先追加到主節點的日誌檔案中,然後廣播到從節點,從節點收到日誌資訊,是提交日誌後返回ACK,還是什麼時候提交呢?
  3. 日誌如何保證唯一。
  4. 如何處理網路出現分割槽。

我相信讀者朋友肯定還有更多的疑問,本文不打算來回答上述疑問,而是帶著這些問題進入到RocketMQ多副本的學習中,通過原始碼分析RocketMQ DLedger的實現後,再來重新總結raft協議。

親愛的讀者們,讀到這裡了,煩請點個贊,謝謝,下一篇將重點分析RocketMQ Dledger 多副本模組如何實現 raft 協議的選主。


作者介紹:丁威,《RocketMQ技術內幕》作者,RocketMQ 社群佈道師,公眾號:中介軟體興趣圈 維護者,目前已陸續發表原始碼分析Java集合、Java 併發包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等原始碼專欄。可以點選連結加入中介軟體知識星球 ,一起探討高併發、分散式服務架構,交流原始碼。

相關推薦

RocketMQ 副本前置初探raft協議

目錄 1、Leader選舉 1.1 一輪投票中,只有一個節點發起投票的情況 1.2 一輪投票中,超過一個節點發起投票的情況 1.3 思考如何實現Raft選主 2、日誌複製

16、iOS線程NSThread

val thread rec getc ive 同時 開放 orm 通信 一、什麽是NSThread   NSThread是基於線程使用,輕量級的多線程編程方法(相對GCD和NSOperation),一個NSThread對象代表一個線程,需要手動管理線程的生命周期,處理線

原始碼分析Elastic-Job前置Spring自定義名稱空間原理

在Spring中使用Elastic-Job的示例如下: <!--配置作業註冊中心 --> <reg:zookeeper id="regCenter" server-lists="${gis.dubbo.registry.address}"

iOS執行緒NSThread簡單介紹和使用

一、什麼是NSThread NSThread是基於執行緒使用,輕量級的多執行緒程式設計方法(相對GCD和NSOperation),一個NSThread物件代表一個執行緒, 需要手動管理執行緒的生命週期

iOS執行緒NSThread

原文 一、什麼是NSThread NSThread是基於執行緒使用,輕量級的多執行緒程式設計方法(相對GCD和NSOperation),一個NSThread物件代表一個執行緒,需要手動管理執行緒的生命週期,處理執行緒同步等問題。 二、NSThread

基於 raft 協議RocketMQ DLedger 副本日誌複製設計原理

目錄 1、RocketMQ DLedger 多副本日誌複製流程圖 1.1 RocketMQ DLedger 日誌轉發(append) 請求流程圖 1.2 RocketMQ DLedger 日誌仲裁流程圖 1.

《Java從入門到放棄》入門hibernate中的表對應關系

java hibernate onetomany hibernate中的對應關系其實就是數據庫中表的對應關系,就跟某些電影中的某些場景是一樣一樣滴。比如可以是一男一女,還可以是一男多女,更可以是多男一女,最後最後最後還可以是多男多女!!!有些不純潔的看官肯定已經開始想歪了吧···,我還是上圖吧!請

《Java從入門到放棄》入門hibernate中的表對應關系(二)

文件中 nas join upx proxy n2n pla sta int 前一篇講完了一對多的關系,通過與JDBC對比應該能發現,是不是比JDBC簡單了很多? 我們只需要把對象只間的包含或對應關系理清楚,完全不用我們自己來寫SQL語句。所以使用hibernate框架後,

第九面向對象之態與封裝

bst 如果 正常 允許 階段 public rop 序列類型 邏輯 一 多態 多態指的是一類事物有多種形態 動物有多種形態:人,狗,豬(咳咳~人也是猴子進化來的,不允許反駁) import abc class Animal(metaclass=abc.A

Python金融系列第八Fama-French 因子模型

作者:chen_h 微訊號 & QQ:862251340 微信公眾號:coderpai 第一篇:計算股票回報率,均值和方差 第二篇:簡單線性迴歸 第三篇:隨機變數和分佈 第四篇:置信區間和假設檢驗 第五篇:多元線性迴歸和殘差分析 第六篇:現代投資組合

CCF2013-12-1出現次數最的數

問題描述   給定n個正整數,找出它們中出現次數最多的數。如果這樣的數有多個,請輸出其中最小的一個。 輸入格式   輸入的第一行只有一個正整數n(1 ≤ n ≤ 1000),表示數字的個數。   輸入的第二行有n個整數s1, s2, …, sn (1 ≤ si ≤ 10000, 1 ≤ i ≤ n)

【搞定Java併發程式設計】第4執行緒概述~下篇

上一篇:多執行緒上篇:https://blog.csdn.net/pcwl1206/article/details/84837530 目  錄: 1、等待/喚醒機制 2、執行緒中斷 3、執行緒終止 4、執行緒休眠sleep 5、執行緒讓步yield() 6、jo

【搞定Java併發程式設計】第3執行緒概述~上

上一篇:併發基礎概述:https://blog.csdn.net/pcwl1206/article/details/84833911 目  錄: 1、什麼是執行緒 2、執行緒的建立 2.1、Thread和Runnable簡介 2.2、Thread和Runnable的異同

第十四Spring Boot+MyBatis配置資料來源

說起多資料來源,一般都來用來解決主從模式或者業務比較複雜需要連線不同的分庫來支援業務。本篇文章主要講解後者的模式,利用AOP動態切換來達到專案訪問不同資料來源。 構架工程 建立一個springboot工程,在其pom檔案加入: <dependency> &

【SSH三大框架】Hibernate基礎第十二load()懶載入分析以及一對一、一對對一、懶載入的分析

一、懶載入的定義: 懶載入:在WEB應用程式中,經常會需要查詢資料庫,系統的響應速度在很大程度上是與資料庫互動的響應。因此,如果能夠優化與資料庫的互動速度,則能夠大大提高WEB應用的響應速度。 例如:當有一個Student類和一個Teacher類。當我們載入一個學生的所有資

RocketMQ——ConsumerPULL模式下的訊息消費(DefaultMQPullConsumer)

1 應用層的使用方式 在應用層初始化DefaultMQPullConsumer類,然後呼叫該類的start方法啟動Consumer;接下來的消費步驟如下: 1、呼叫DefaultMQPullConsumer.fetchSubscribeMessageQueu

【SSH三大框架】Hibernate基礎第七一對關聯關係的操作

相對於上文的多對一關係,這裡又說明下一對多的關聯關係。 在上文中,我們描述了多對一的關係,在關係資料庫中也是多對一的關係,並且還是一對多的關係。但是,僅僅如此是不夠的,Hibernate是一種面向物件的結構,在Hibernate中仍然是多對一的關係,但是沒有一對多,所以我們

RocketMQ——ConsumerPUSH模式下消費訊息(順序和併發兩種)

1 接受並處理Broker返回的響應訊息 當傳送拉取訊息在Broker返回響應訊息之後呼叫NettyRemotingAbstract.processMessageReceived(ChannelHandlerContext ctx, RemotingComma

SpringBoot進階教程 | 第一YML文件塊實現環境配置

你是否為SpringBoot一個功能多個yml和多個properties檔案區分不同執行環境配置,經常為這些配置檔案的管理而頭疼,現在通過這篇文章,將徹底解決你的煩惱,這篇文篇介紹,怎麼通過yml檔案構建多文件塊,區分不同環境配置,自由切換不同環境啟動專案,一個

LinuxC執行緒程式設計第五執行緒通訊(Condition)

        執行緒同步還有一種情況,執行緒1需要等某個條件成立才能繼續往下執行,如果這個條件不成立,執行緒1就阻塞等待,執行緒2在執行某個條件成立了就喚醒執行緒1。這個和Java中的wait()和notify()其實是一樣的 初始化與銷燬通訊條件 #include &