Raft算法詳解

Raft算法屬于Multi-Paxos算法,它是在Multi-Paxos思想的基礎上,做了一些簡化和限制,比如增加了日志必須是連續的,只支持領導者、跟隨者和候選人三種狀態,在理解和算法實現上都相對容易許多

從本質上說,Raft算法是通過一切以領導者為準的方式,實現一系列值的共識和各節點日志的一致

1、領導者選舉

1)、成員身份

Raft算法支持領導者(Leader)、跟隨者(Follower)和候選人(Candidate)3種狀態:

  • 跟隨者:接收和處理來自領導者的消息,當等待領導者心跳信息超時的時候,就主動站出來,推薦自己當候選人
  • 候選人:候選人將向其他節點發送請求投票(RequestVote)RPC消息,通知其他節點來投票,如果贏得了大多數選票,就晉升當領導者
  • 領導者:負責處理寫請求、管理日志復制和不斷地發送心跳信息,通知其他節點“我是領導者,我還活著,你們現在不要發起新的選舉,找個新領導者來替代我”

Raft算法是強領導者模型,集群中只能有一個領導者

2)、選舉領導者的過程

在初始狀態下,集群中所有的節點都是跟隨者狀態

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

Raft算法實現了隨機超時時間的特性,每個節點等待領導者心跳信息的超時時間間隔是隨機的。上圖中,集群中沒有領導者,而節點A的等待超時時間最小,它會最先因為沒有等到領導者的心跳信息,發生超時

這時,節點A增加自己的任期編號,并推舉自己為候選人,先給自己投上一張選票,然后向其他節點發送請求投票RPC消息,請它們選舉自己為領導者

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

如果其他節點接收到候選人A的請求投票RPC消息,在編號為1的這屆任期內,也還沒有進行過投票,那么它將把選票投給節點A,并增加自己的任期編號

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

如果候選人在選舉超時時間內贏得了大多數的選票,那么它就會成為本屆任期內新的領導者

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

節點A當選領導者后,它將周期性地發送心跳消息,通知其他服務器我是領導者,阻止跟隨者發起新的選舉

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

3)、節點間如何通訊?

在Raft算法中,服務器節點間的溝通聯絡采用的是遠程過程調用(RPC),在領導者選舉中,需要用到這兩類的RPC:

  • 請求投票(RequestVote)RPC:是由候選人在選舉期間發起,通知各節點進行投票
  • 日志復制(AppendEntries)RPC:是由領導者發起,用來復制日志和提供心跳消息

4)、什么是任期?

Raft算法中每個任期由單調遞增的數字(任期編號)標識,任期編號是隨著選舉的舉行而變化的

  1. 跟隨者在等待領導者心跳信息超時后,推舉自己為候選人時,會增加自己的任期編號,比如節點A的任期編號為0,那么在推舉自己為候選人時,會將自己的任期編號增加為1
  2. 如果一個服務器節點,發現自己的任期編號比其他節點小,那么它會更新自己的任期編號到較大的編號值,比如節點B的任期編號是0,當收到來自節點A的請求投票RPC消息時,因為消息中包含了節點A的任期編號,且編號為1,那么節點B將把自己的任期編號更新為1
  3. 如果一個候選人或者領導者,發現自己的任期編號比其他節點小,那么它會立即恢復成跟隨者狀態。比如分區錯誤恢復后,任期編號為3的領導者節點B,收到來自新領導者的包含任期編號為4的心跳消息,那么節點B將立即恢復成跟隨者狀態
  4. 如果一個節點接收到一個包含較小的任期編號值的請求,那么它會直接拒絕這個請求。比如節點C的任期編號為4,收到包含任期編號為3的請求投票RPC消息,那么它將拒絕這個消息

5)、選舉有哪些規則?

  1. 領導者周期性地向所有跟隨者發送心跳消息(即不包含日志項的日志復制RPC消息),通知大家我是領導者,組織跟隨者發起新的選舉

  2. 如果在指定時間內,跟隨者沒有接收到來自領導者的消息,那么它就認為當前沒有領導者,推舉自己為候選人,發起領導者選舉

  3. 在一次選舉中,贏得大多數選票的候選人,將晉升為領導者

  4. 在一個任期內,領導者一直都會是領導者,直到它自身出現問題(比如宕機),或者因為網絡延遲,其他節點發起一輪新的選舉

  5. 在一次選舉中,每一個服務器節點最多會對一個任期編號投出一張選票,并且按照先來先服務的原則進行投票。比如節點C的任期編號為3,先收到了一個包含任期編號為4的投票請求(來自節點A),然后又收到了一個包含任期編號為4的投票請求(來自節點B)。那么節點C將會把唯一一張選票投給節點A,當再收到節點B的投票請求RPC消息時,對于編號為4的任期,已沒有選票可投了

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

  1. 日志完整性高的跟隨者(也就是最后一條日志項對應的任期編號值更大,索引號更大)拒絕投票給日志完整性低的候選人。比如節點B的任期編號為3,節點C的任期編號為4,節點B的最后一條日志項對應的任期編號為3,而節點C為2,那么當節點C請求節點B投票給自己時,節點B將拒絕投票

在這里插入圖片描述

選舉是跟隨者發起的,推舉自己為候選人;大多數選票是指集群成員半數以上的選票;大多數選票規則的目標,是為了保證在一個給定的任期內最多只有一個領導者

6)、隨機超時時間是什么?

Raft算法使用隨機選舉超時時間的方法,把超時時間都分散開來,在大多數情況下只有一個服務器節點先發起選舉,而不是同時發起選舉,這樣就能減少因選票瓜分導致選舉失敗的情況

在Raft算法中,隨機超時時間有2種含義:

  1. 跟隨者等待領導者心跳信息超時的時間間隔是隨機的
  2. 如果候選人在一個隨機時間間隔內,沒有贏得過半票數,那么選舉就無效了,然后候選人發起新一輪的選舉,也就是說,等待選舉超時的時間間隔是隨機的

7)、補充

1)Raft算法的強領導者模型選舉限制和局限如下:

  1. 讀寫請求和數據轉發壓力落在領導者節點,相當于單機,性能和吞吐量也會受到限制
  2. 大規模跟隨者的集群,領導者需要承擔大量元數據維護和心跳通知的成本
  3. 領導者單點問題,故障后直到新領導者選舉出來期間集群不可用
  4. 隨著候選人規模增長,收集半數以上投票的成本更大

2)強領導者模型會限制集群的寫性能,有什么辦法能突破Raft集群的寫性能瓶頸呢?

參考Kafka的分區和ES的主分片副本分片這種機制,雖然寫入只能通過Leader寫,但每個Leader可以負責不同的片區,來提高寫入的性能

2、日志復制

1)、如何理解日志?

副本數據是以日志的形式存在的,日志是由日志項組成,日志項是一種數據格式,它主要包含用戶指定的數據,也就是指令(Command),還包含一些附加信息,比如索引值(Log index)、任期編號(Term)

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

  • 指令:一條由客戶端請求指定的、狀態機需要執行的指令,可以理解成客戶端指定的數據
  • 索引值:日志項對應的整數索引值,用來標識日志項的,是一個連續的、單調遞增的證書號碼
  • 任期編號:創建這條日志項的領導者的任期編號

2)、如何復制日志?

首先,領導者通過日志復制(AppendEntries)RPC消息,將日志項復制到集群其他節點上

接著,如果領導者接收到大多數的復制成功響應后,它將日志項應用到它的狀態機,并返回成功給客戶端。如果領導者沒有接收到大多數的復制成功響應,那么就返回錯誤給客戶端

領導者將日志項應用到它的狀態機,怎么沒通知跟隨者應用日志項呢?

因為領導者的日志復制RPC消息或心跳消息,包含了當前最大的、將會被提交的日志項索引值。所以通過日志復制RPC消息或心跳消息,跟隨者就可以知道領導者的日志提交位置信息

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

  1. 接收到客戶端請求后,領導者基于客戶端請求中的指令,創建一個新日志項,并附加到本地日志中
  2. 領導者通過日志復制RPC,將新的日志復制到其他的服務器
  3. 當領導者將日志項成功復制到大多數的服務器上的時候,領導者會將這條日志項應用到它的狀態機中
  4. 領導者將執行的結果返回給客戶端
  5. 當跟隨者接收到心跳消息,或者新的日志復制RPC消息后,如果跟隨者發現領導者已經提交了某條日志項,而它還沒應用,那么跟隨者就將這條日志項應用到本地的狀態機上

3)、如何實現日志的一致?

在Raft算法中,領導者通過強制跟隨者直接復制自己的日志項,處理不一致日志。也就是說,Raft是通過以領導者的日志為準,來實現各節點日志的一致性的

  1. 首先,領導者通過日志復制RPC的一致性檢查,找到跟隨者節點上與自己相同日志項的最大索引值。也就是說,這個索引值之前的日志,領導者和跟隨者是一致的,之后的日志是不一致的
  2. 然后,領導者強制跟隨者更新覆蓋不一致的日志項,實現日志的一致

引入2個新變量:

  • PrevLogEntry:表示當前要復制的日志項,前面一條日志項的索引值。比如下圖中,如果領導者將索引值為8的日志項發送給跟隨者,那么此時PrevLogEntry值為7
  • PrevLogTerm:表示當前要復制的日志項,前面一條日志項的任期編號,比如在圖中,如果領導者將索引值為8的日志項發送給跟隨者,那么此時PrevLogTerm值為4

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwMzc4MDM0,size_16,color_FFFFFF,t_70#pic_center

  1. 領導者通過日志復制RPC消息,發送當前最新日志項到跟隨者,這個消息的PrevLogEntry值為7、PrevLogTerm值為4
  2. 如果跟隨者在它的日志中,找不到PrevLogEntry值為7、PrevLogTerm值為4的日志項,也就是說它的日志和領導者的不一致了,那么跟隨者就會拒絕接收新的日志項,并返回失敗消息給領導者
  3. 這時,領導者會遞減要復制的日志項的索引值,并發送新的日志項到跟隨者,這個消息的PrevLogEntry值為6、PrevLogTerm值為3
  4. 如果跟隨者在它的日志中,找到了PrevLogEntry值為6、PrevLogTerm值為3的日志項,那么日志復制RPC返回成功,這樣一來,領導者就知道在PrevLogEntry值為6、PrevLogTerm值為3的位置,跟隨者的日志項與自己相同
  5. 領導者通過日志復制RPC復制并更新覆蓋該索引值之后的日志項(也就是不一致的日志項),最終實現了集群各節點日志的一致

領導者通過日志復制RPC一致性檢查,找到跟隨者節點上與自己相同日志項的最大索引值,然后復制并更新覆蓋該索引值之后的日志項,實現了各節點日志的一致。跟隨者中的不一致日志項會被領導者的日志覆蓋,而且領導者從來不會覆蓋或者刪除自己的日志

4)、補充

1)領導者接收到大多數的“復制成功”響應后,就會將日志應用到它自己的狀態機,然后返回“成功”響應客戶端。如果此時有個節點不在“大多數”中,也就是說它接收日志項失敗,那么在這種情況下,Raft會如何處理實現日志的一致呢?

處理日志項一致通過RPC一致性檢查,找到跟隨者中與自己相同日志項的最大索引,然后把后面的日志項同步過去,讓跟隨者復制更新

2)Raft在處理日志不一致時會給跟隨者發送RPC一致性檢查,找到和自己相同日志項的最大值,這里是對每個跟隨者而言的還是所有的跟隨者而言的?

日志復制信息對每個跟隨者都要單獨維護的

參考:

07 | Raft算法(一):如何選舉領導者?

08 | Raft算法(二):如何復制日志?


---------------------
作者:邋遢的流浪劍客
來源:CSDN
原文:https://blog.csdn.net/qq_40378034/article/details/117404484
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283912.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283912.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283912.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

淘寶彈性布局方案lib-flexible研究

1. lib-flexible不能與響應式布局兼容 先說說響應式布局的一些基本認識: 響應式布局的表現是:網頁通過css媒介查詢判斷可視區域的寬度,在不同的范圍應用不同的樣式,以便在不同尺寸的設備上呈現最佳的界面效果。典型的例子是&#…

[No0000DB]C# FtpClientHelper Ftp客戶端上傳下載重命名 類封裝

using System; using System.Diagnostics; using System.IO; using System.Text; using Shared;namespace Helpers {public static class FileHelper{#region Methods/// <summary>/// 向文本文件的尾部追加內容/// </summary>/// <param name"filePa…

WPF效果第一百九十四篇之伸縮面板

前面一篇玩耍了一下登錄實現效果;今天在原來的基礎上來玩耍一下伸縮面板的效果;閑話不多扯直接看效果:1、關于前臺簡單布局:2、左側面板伸縮動畫&#xff1a;<Storyboard x:Key"ShowConfigSb"><ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty…

你不知道的JavaScript(二)

第三章 原生函數 JS有很多原生函數&#xff0c;為基本的數據類型值提供了封裝對象&#xff0c;String&#xff0c;Number&#xff0c;Boolean等。我們可以通過{}.call.toString()來查看所有typeof返回object的對象的內置屬性[[class]],這個屬性無法直接訪問。我們基本類型調用的…

[轉]guava快速入門

Guava工程包含了若干被Google的 Java項目廣泛依賴 的核心庫&#xff0c;例如&#xff1a;集合 [collections] 、緩存 [caching] 、原生類型支持 [primitives support] 、并發庫 [concurrency libraries] 、通用注解 [common annotations] 、字符串處理 [string processing] 、I…

數據庫編程1 Oracle 過濾 函數 分組 外連接 自連接

【本文謝絕轉載原文來自http://990487026.blog.51cto.com】<大綱>數據庫編程1 Oracle 過濾 函數 分組 外連接 自連接本文實驗基于的數據表:winsows安裝好Oracle11g之后,開始實驗SQLplus 登陸 ORaclesqlplus 退出的方式查看用戶之下有什么表查看表的所有記錄&#xff0c;不…

【.NET 6】開發minimal api以及依賴注入的實現和代碼演示

前言&#xff1a;.net 6 LTS版本發布已經有一段時間了。此處做一個關于使用.net 6 開發精簡版webapi&#xff08;minimal api&#xff09;的入門教程演示。1、新建一個項目。此處就命名為 SomeExample:2、選擇 .net6版本&#xff0c;并且此處先去掉HTTPS配置以及去掉使用控制器…

(轉載)VS2010/MFC編程入門之四(MFC應用程序框架分析)

上一講雞啄米講的是VS2010應用程序工程中文件的組成結構&#xff0c;可能大家對工程的運行原理還是很模糊&#xff0c;理不出頭緒&#xff0c;畢竟跟C編程入門系列中的例程差別太大。這一節雞啄米就為大家分析下MFC應用程序框架的運行流程。 一.SDK應用程序與MFC應用程序運行過…

個人博客開發-開篇

邁出第一步&#xff1a; 很久以前就有這個想法&#xff0c;自己動手開發一套個人博客系統&#xff0c;終于&#xff0c;現在開始邁出了第一步。做這件事一點是做一個有個人風格的博客系統&#xff0c;第二點是對做這件事所使用的技術棧進行學習&#xff0c;所謂最好的學習就是實…

2022年中國中小學教育信息化行業研究報告

教育信息化丨研究報告 核心摘要&#xff1a; 背景篇 目前&#xff0c;我國中小學教育主要呈現信息時代教育的特征&#xff0c;智能時代教育特征初露端倪&#xff1b;中小學教育信息化正從量變邁向質變&#xff0c;創新引領與生態變革成為行業縱深的主旋律&#xff1b; 2021年…

使用curl指令發起websocket請求

昨日的文章沒指出websocket請求協商切換的精髓&#xff0c;刪除重發。前文相關&#xff1a;? .NET WebSockets 核心原理初體驗[1]? SignalR 從開發到生產部署避坑指南[2]tag&#xff1a;瀏覽器--->nginx--> server其中提到nginx默認不會為客戶端轉發Upgrade、Connectio…

Yii 2 的安裝 之 踩坑歷程

由于剛接觸yii2 ,決定先裝個試試&#xff1b;可是這一路安裝差點整吐血&#xff0c;可能還是水平有限吧&#xff0c; 但還是想把這個過程分享出來&#xff0c;讓遇到同樣問題的同學有個小小的參考&#xff0c;好了言歸正傳&#xff01;&#xff01; <(~.~)> 下面是安裝流…

設計模式之代理模式(上) 靜態代理與JDK動態代理

2019獨角獸企業重金招聘Python工程師標準>>> 代理模式 給某一個對象提供一個代理&#xff0c;并由代理對象控制對原對象的引用。靜態代理 靜態代理是由我們編寫好的類&#xff0c;在程序運行之前就已經編譯好的的類&#xff0c;此時就叫靜態代理。 說理論還是比較懵…

mysql 分頁查詢

使用limit函數 limit關鍵字的用法&#xff1a; LIMIT [offset,] rows offset指定要返回的第一行的偏移量&#xff0c;rows第二個指定返回行的最大數目。初始行的偏移量是0(不是1)。轉載于:https://www.cnblogs.com/xping/p/6703986.html

WPF 實現更換主題色

WPF 實現更換主題色WPF 使用 WPFDevelopers.Minimal 如何更換主題色作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&a…

vue3與vue2的區別

先來說說當下市場開發使用的問題&#xff0c;目前2021年使用vue3開發的企業還是少&#xff0c;基本上都還是以vue2的形式進行開發&#xff0c;vue3的開發模式跟react很像&#xff0c;這時候有人就會想那我學vue3有用么&#xff0c;淦&#xff0c;他喵的&#xff0c;先別激動&am…

Spring Data REST API集成Springfox、Swagger

原文: Documenting a Spring Data REST API with Springfox and Swagger 使用Spring Date REST&#xff0c;你可以迅速為Spring Date repositories的創建REST API&#xff0c;并提供CRUD和更多功能。然而&#xff0c;在嚴謹的API開發過成功&#xff0c;您還希望擁有自動生成的最…

【系統設計】S3 對象存儲

在本文中&#xff0c;我們設計了一個類似于 Amazon Simple Storage Service (S3) 的對象存儲服務。S3 是 Amazon Web Services (AWS) 提供的一項服務&#xff0c; 它通過基于 RESTful API 的接口提供對象存儲。根據亞馬遜的報告&#xff0c;到 2021 年&#xff0c;有超過 100 萬…

轉: telnet命令學習

1.每天一個linux命令&#xff08;58&#xff09;&#xff1a;telnet命令 轉自&#xff1a; http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用來遠程登錄。telnet程序是基于TELNET協議的遠程登錄客戶端程序。Telnet協議是TCP/IP協議族中的一員&a…