raft協議 MySQL 切換_Raft 協議實戰系列(二)—— 選主

注:本文原創,轉載請標明出處。

歡迎轉發、關注微信公眾號:Q的博客。 不定期發送干貨,實踐經驗、系統總結、源碼解讀、技術原理。

本文目的

筆者期望通過系列文章幫助讀者深入理解Raft協議并能付諸于工程實踐中,同時解讀不易理解或容易誤解的關鍵點。

該系列會從原理、源碼、實踐三個部分為大家講解Raft算法,本文為《Raft實戰》系列第二篇:

原理部分我們會結合 Raft 論文講解 Raft 算法思路,整體分篇會遵循 Raft 的模塊化思想,分別講解 Leader election、Log replication、Safety、Cluster membership change、Log compaction 等。

源碼部分我們會通過分析 hashicorp/raft 來學習一個工業界的 Raft 實現,hashicorp/raft 是 Consul 的底層依賴。

實踐部分我們會基于 hashicorp/raft 來實現一個簡單的分布式 kv 存儲,以此作為系列的收尾。

什么是選主

選主(Leader election)就是在分布式系統內抉擇出一個主節點來負責一些特定的工作。在執行了選主過程后,集群中每個節點都會識別出一個特定的、唯一的節點作為leader。

我們開發的系統如果遇到選主的需求,通常會直接基于 zookeeper 或 etcd 來做,把這部分的復雜性收斂到第三方系統。然而作為 etcd 基礎的 raft 自身也存在“選主”的概念,這是兩個層面的事情:基于 etcd 的選主指的是利用第三方 etcd 讓集群對誰做主節點的決策達成一致,技術上來說利用的是 etcd 的一致性狀態機、lease 以及 watch 機制,這個事情也可以改用單節點的 MySQL/Redis 來做,只是無法獲得高可用性;而 raft 本身的選主則指的是在 raft 集群自身內部通過票選、心跳等機制來協調出一個大多數節點認可的主節點作為集群的 leader 去協調所有決策。

當你的系統利用 etcd 來寫入誰是主節點的時候,這個決策也在 etcd 內部被它自己集群選出的主節點處理并同步給其它節點。

Raft 為什么要進行選主?

按照論文所述,原生的 Paxos 算法使用了一種點對點(peer-to-peer)的方式,所有節點地位是平等的。在理想情況下,算法的目的是制定一個決策,這對于簡化的模型比較有意義。但在工業界很少會有系統會使用這種方式,當有一系列的決策需要被制定的時候,先選出一個 leader 節點然后讓它去協調所有的決策,這樣算法會更加簡單快速。

此外,和其它一致性算法相比,raft 賦予了 leader 節點更強的領導力,稱之為 Strong Leader。比如說日志條目只能從 leader 節點發送給其它節點而不能反著來,這種方式簡化了日志復制的邏輯,使 raft 變得更加簡單易懂。

Raft選主過程

下圖的節點狀態轉移圖,我們在前一篇文章已經看到了,但只是做了簡單的描述,接下來我們會結合具體的Leader election細節來深刻理解節點的狀態轉換。

bf16218b0ee735131be12e501f100957.png

*圖名:節點狀態圖

Follower狀態轉移過程

Raft 的選主基于一種心跳機制,集群中每個節點剛啟動時都是 follower 身份(Step: starts up),leader 會周期性的向所有節點發送心跳包來維持自己的權威,那么首個 leader 是如何被選舉出來的呢?方法是如果一個 follower 在一段時間內沒有收到任何心跳,也就是選舉超時,那么它就會主觀認為系統中沒有可用的 leader,并發起新的選舉(Step: times out, starts election)。

這里有一個問題,即這個“選舉超時時間”該如何制定?如果所有節點在同一時刻啟動,經過同樣的超時時間后同時發起選舉,整個集群會變得低效不堪,極端情況下甚至會一直選不出一個主節點。Raft 巧妙的使用了一個隨機化的定時器,讓每個節點的“超時時間”在一定范圍內隨機生成,這樣就大大的降低了多個節點同時發起選舉的可能性。

3540e494487f90e60a1b602f80104583.png

*圖解:一個五節點Raft集群的初始狀態,所有節點都是follower身份,term為1,且每個節點的選舉超時定時器不同

若 follower 想發起一次選舉,follower 需要先增加自己的當前 term,并將身份切換為 candidate。然后它會向集群其它節點發送“請給自己投票”的消息(RequestVote RPC)。

46dabc4d360828208451d295c19c90f3.png

*圖解:S1 率先超時,變為 candidate,term + 1,并向其它節點發出拉票請求

Candicate狀態轉移過程

Follower 切換為 candidate 并向集群其他節點發送“請給自己投票”的消息后,接下來會有三種可能的結果,也即上面節點狀態圖中 candidate 狀態向外伸出的三條線。

1. 選舉成功(Step: receives votes from majority of servers)

當candicate從整個集群的大多數(N/2+1)節點獲得了針對同一 term 的選票時,它就贏得了這次選舉,立刻將自己的身份轉變為 leader 并開始向其它節點發送心跳來維持自己的權威。

909d7cf481e5e6a14c333e873240d2a6.png

*圖解:“大部分”節點都給了S1選票

6cf18d12cb75a1da9020d55339e645bc.png

*圖解:S1變為leader,開始發送心跳維持權威

每個節點針對每個 term 只能投出一張票,并且按照先到先得的原則。這個規則確保只有一個 candidate 會成為 leader。

2. 選舉失敗(Step: discovers current leader or new term)

Candidate 在等待投票回復的時候,可能會突然收到其它自稱是 leader 的節點發送的心跳包,如果這個心跳包里攜帶的 term 不小于 candidate 當前的 term,那么 candidate 會承認這個 leader,并將身份切回 follower。這說明其它節點已經成功贏得了選舉,我們只需立刻跟隨即可。但如果心跳包中的 term 比自己小,candidate 會拒絕這次請求并保持選舉狀態。

68125afcea3039efd73accdd28964e75.png

*圖解:S4、S2 依次開始選舉

bbef2463f50c7d7fdb06dda1363fa951.png

*圖解:S4 成為 leader,S2 在收到 S4 的心跳包后,由于 term 不小于自己當前的 term,因此會立刻切為 follower 跟隨S4

3. 選舉超時(Step: times out, new election)

第三種可能的結果是 candidate 既沒有贏也沒有輸。如果有多個 follower 同時成為 candidate,選票是可能被瓜分的,如果沒有任何一個 candidate 能得到大多數節點的支持,那么每一個 candidate 都會超時。此時 candidate 需要增加自己的 term,然后發起新一輪選舉。如果這里不做一些特殊處理,選票可能會一直被瓜分,導致選不出 leader 來。這里的“特殊處理”指的就是前文所述的隨機化選舉超時時間。

0b39d9abcc865eade82afde49d6ed2f0.png

*圖解:S1~S5都在參與選舉

e323313b68bdedc24855834e50e80263.png

*圖解:沒有任何節點愿意給他人投票

e7aa16b30bd5fb2704542ae0f342cc18.png

*圖解:如果沒有隨機化超時時間,所有節點將會繼續同時發起選舉……

以上便是 candidate 三種可能的選舉結果。

Leader 切換狀態轉移過程

節點狀態圖中的最后一條線是:discovers server with higher term。想象一個場景:當 leader 節點發生了宕機或網絡斷連,此時其它 follower 會收不到 leader 心跳,首個觸發超時的節點會變為 candidate 并開始拉票(由于隨機化各個 follower 超時時間不同),由于該 candidate 的 term 大于原 leader 的 term,因此所有 follower 都會投票給它,這名 candidate 會變為新的 leader。一段時間后原 leader 恢復了,收到了來自新leader 的心跳包,發現心跳中的 term 大于自己的 term,此時該節點會立刻切換為 follower 并跟隨的新 leader。

上述流程的動畫模擬如下:

9ca7523f0e89e2836d13819ab3ad785b.png

*圖解:S4 作為 term2 的 leader

9c17e6375fa99844501caa35e94be8a0.png

*圖解:S4 宕機,S5 即將率先超時

d6d1d8ad5352a128bbc6a7cbee8fee41.png

*圖解:S5 當選 term3 的 leader

230fc51ccd4bbdb20de0198a24e49bf9.png

*圖解:S4 宕機恢復后收到了來自 S5 的 term3 心跳

da6befbfb32c438370d323d06f4eb997.png

*圖解:S4 立刻變為 S5 的 follower

以上就是 raft 的選主邏輯,但還有一些細節(譬如是否給該 candidate 投票還有一些其它條件)依賴算法的其它部分基礎,我們會在后續“安全性”一篇描述。

當票選出 leader 后,leader 也該承擔起相應的責任了,這個責任是什么?就是下一篇將介紹的“日志復制”~

歡迎轉發、關注微信公眾號:Q的博客,不定期發送干貨,實踐經驗、系統總結、源碼解讀、技術原理。

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

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

相關文章

codeforce Pashmak and Buses(dfs枚舉)

1 /*2 題意:n個同學,k個車, 取旅游d天!3 要求所有的學生沒有兩個或者兩個以上的在同一輛車上共同帶d天! 輸出可行的方案!4 5 對于d行n列的矩陣,第i行第j列表示的是第i天第j個同學所…

怎樣用mysql查詢測試_如何測試數據庫查詢優化器

我一直認為,查詢優化器(Query Optimizer,后面簡稱優化器)一直是數據庫領域 Top 級別的 hardcore 技術,自己也一直嘗試去深入理解,但每每看到 TiDB 代碼里面那一大坨 plan 的代碼,我就望而生畏了,就像是『可…

poj2060Taxi Cab Scheme(二分圖匹配)

1 /*2 題意: 出租車 有一個出發的時間,從點(a, b)到點(c, d),時間為3 abs(a-c)abs(b-d)! 一輛車可以在運完一個乘客后運另一個乘客, 4 條件是此車要在預約開始前一分鐘之前到達出發地,…

二級java考什么_計算機二級Java考試資料!

Where領?基本要求1 . 掌握 Java 語言的特點、實現機制和體系結構。2 . 掌握 Java 語言中面向對象的特性。3 . 掌握 Java 語言提供的數據類型和結構。4 . 掌握 Java 語言編程的基本技術。5 . 會編寫 Java 用戶界面…

二分匹配最大匹配的理解(附圖解)

定義一個PXP的有向圖中,路徑覆蓋就是在圖中找一些路徑,使之覆蓋了圖中的所有頂點,且任何一個頂點有且只有一條路徑與之關聯;(如果把這些路徑中的每條路徑從它的起始點走到它的終點,那么恰好可以經過圖中的每…

poj 2226 Muddy Fields(合理建圖+二分匹配)

1 /*2 題意:用木板蓋住泥濘的地方,不能蓋住草。木板任意長!可以重疊覆蓋! *表示泥濘的地方,.表示草!3 思路:4 首先讓我們回憶一下HDU 2119 Matrix這一道題,一個矩陣…

java驗證碼工具_java 驗證碼工具

importjavax.imageio.ImageIO;import java.awt.*;importjava.awt.image.BufferedImage;importjava.io.IOException;importjava.io.OutputStream;importjava.util.Random;public classCaptchaUtils {private final static Object lock newObject();/*** 圖片的寬度。*/private …

Floyd算法的理解

轉載于:https://www.cnblogs.com/hujunzheng/p/3919226.html

http get post java_java發送http的get、post請求實現代碼

Http請求類package wzh.Http;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;public class HttpRe…

java string的作用_淺談java String不可變的好處

一、java內部String類的實現:java 8:public final class Stringimplements java.io.Serializable, Comparable, CharSequence {/** The value is used for character storage. */private final char value[];}java 9 及之后:(使用coder標識了…

34988 Happy Reversal(二進制去取反)

1 /*2 題意:給多個二進制數,對某些數進行按位取反操作!3 然后從中找到最大數和最小數,并輸出他們的差值! 4 注意:所有的數都是整數,包括取反之后5 6 思路:一個n為二進…

java vim ide_Vim配置Java IDE

首先安裝vim (當然做java 開發要裝jdk 這個就不說了)emerge -av vim (gentoo 系統上安裝vim 的命令,你可以用rpm ,apt-get )給vim 安裝 javacomplete 插件http://www.vim.org/scripts/script.php?script_id1785 這個插件的作用是實現一部分代碼提示功能 比如你輸入 System…

java中線程存活和線程執行的問題!

1 /*2 下面的程序會出現下面的情況,當Thread-0, Thread-1, Thread-2都被wait的時候,可能會同時蘇醒3 Thread-0 put4 Thread-1 put5 Thread-2 put6 Thread-3 get//在此處,Thread-3拿到鎖之后&#xff0…

java中多線程模擬(多生產,多消費,Lock實現同步鎖,替代synchronized同步代碼塊)...

import java.util.concurrent.locks.*; class DuckMsg{int size;//烤鴨的大小String id;//烤鴨的廠家和標號DuckMsg(){}DuckMsg(int size, String id){this.sizesize;this.idid;}public String toString(){return id " 大小為:" size;} } class Duck{private int …

java encode 空格_javaWeb中URLEncoder.encode空格問題

近期開發一個在線坐席的功能。發現推送的消息中空格變成了 。查詢發現URLEncoder.encode的問題。曾經用的時候也沒注意過,解決的方法網上是對URLEncoder.encode的之后的字符串進行替換號,這樣的方式假設真的有號那也被替換了。所以應該在URLEncoder.enco…

poj 1386 Play on Words(有向圖歐拉回路)

1 /*2 題意:單詞拼接,前一個單詞的末尾字母和后一個單詞的開頭字母相同3 思路:將一個單詞的開頭和末尾單詞分別做兩個點并建一條有向邊!然后判斷是否存在歐拉回路或者歐拉路 4 5 再次強調有向圖歐拉路或歐拉回路的判定方法&…

java web tomcat 實例_Java Web應用開發實例

[1.GIS的概念 1.1什么是gis 地理信息系統 (GIS, Geographic Information System) 是一種基于計算機的工具,它可以對在地球上存在的東西和發生的事件進行成圖和分析。 GI上次提到了EclipseTomcatLomboz Java Web開發環境的配置,可環…

poj2513Colored Sticks(無向圖的歐拉回路)

1 /*2 題意:將兩端涂有顏色的木棒連在一起,并且連接處的顏色相同!3 思路:將每一個單詞看成一個節點,建立節點之間的無向圖!判斷是否是歐拉回路或者是歐拉路4 5 并查集判通 奇度節點個數等于2或…

java java.lang.enum_源碼閱讀-java基礎-java.lang.Enum

1、引言枚舉類型是 JDK 5 之后引進的一種非常重要的引用類型,可以用來定義一系列枚舉常量。相比與常量(public static final定義),在安全性、指意性、可讀性方面更勝一籌。另外它可以和switch case搭配使用。2、類定義實際上在使用關鍵字enum創建枚舉類型…

java中有關線程的題目

1,看一下下面程序錯誤發生在哪一行! class Test implements Runnable{public void run(Thread t){} }2,輸出結果是什么? class Test{public static void main(String[] args){new Thread(new Runnable(){public void run(){System…