ZooKeeper集群與Leader選舉

說說你對ZooKeeper集群與Leader選舉的理解?

?ZooKeeper是一個開源分布式協調服務、分布式數據一致性解決方案。可基于ZooKeeper實現命名服務、集群管理、Master選舉、分布式鎖等功能。

? 高可用??

為了保證ZooKeeper的可用性,在生產環境中我們使用ZooKeeper集群模式對外提供服務,并且集群規模至少由3個ZooKeeper節點組成。



? 集群至少由3個節點組成??

ZooKeeper其實2個節點也可以組成集群并對外提供服務,但我們使用集群主要目的是為了高可用。如果2個節點組成集群,其中1個節點掛了,另外ZooKeeper節點不能正常對外提供服務。因此也失去了集群的意義。

如果3個節點組成集群,其中1個節點掛掉后,根據ZooKeeper的Leader選舉機制是可以從另外2個節點選出一個作為Leader的,集群可以繼續對外提供服務。



? 并非節點越多越好??

  • 節點越多,使用的資源越多

  • 節點越多,ZooKeeper節點間花費的通訊成本越高,節點間互連的Socket也越多。影響ZooKeeper集群事務處理

  • 節點越多,造成腦裂的可能性越大



? 集群規模為奇數??

集群規模除了考慮自身成本和資源外還要結合ZooKeeper特性考慮:

  • 節省資源

    3節點集群和4節點集群,我們選擇使用3節點集群;5節點集群和6節點集群,我們選擇使用5節點集群。以此類推。因為生產環境為了保證高可用,3節點集群最多只允許掛1臺,4節點集群最多也只允許掛1臺(過半原則中解釋了原因)。同理5節點集群最多允許掛2臺,6節點集群最多也只允許掛2臺。

    出于對資源節省的考慮,我們應該使用奇數節點來滿足相同的高可用性。

  • 集群可用性

    當集群中節點間網絡通訊出現問題時奇數和偶數對集群的影響







? 集群配置??

ZooKeeper集群配置至少需要2處變更:

1、增加集群配置

在{ZK_HOME}/conf/zoo.cfg中增加集群的配置,結構以server.id=ip:port1:port2為標準。

比如下面配置文件中表示由3個ZooKeeper組成的集群:

server.1=localhost:2881:3881
server.2=localhost:2882:3882
server.3=localhost:2883:3883

?

?

2、配置節點id

zoo.cfg中配置集群時需要指定server.id,這個id需要在dataDir(zoo.cfg中配置)指定的目錄中創建myid文件,文件內容就是當前ZooKeeper節點的id。

? 集群角色??

ZooKeeper沒有使用Master/Slave的概念,而是將集群中的節點分為了3類角色:

  • Leader

    在一個ZooKeeper集群中,只能存在一個Leader,這個Leader是集群中事務請求唯一的調度者和處理者,所謂事務請求是指會改變集群狀態的請求;Leader根據事務ID可以保證事務處理的順序性。

    如果一個集群中存在多個Leader,這種現象稱為「腦裂」。試想一下,一個集群中存在多個Leader會產生什么影響?

    相當于原本一個大集群,裂出多個小集群,他們之間的數據是不會相互同步的。「腦裂」后集群中的數據會變得非常混亂。

  • Follower

    Follower角色的ZooKeeper服務只能處理非事務請求;如果接收到客戶端事務請求會將請求轉發給Leader服務器;參與Leader選舉;參與Leader事務處理投票處理。

    Follower發現集群中Leader不可用時會變更自身狀態,并發起Leader選舉投票,最終集群中的某個Follower會被選為Leader。

  • Observer

    Observer與Follower很像,可以處理非事務請求;將事務請求轉發給Leader服務器。

    與Follower不同的是,Observer不會參與Leader選舉;不會參與Leader事務處理投票。

    Observer用于不影響集群事務處理能力的前提下提升集群的非事務處理能力。

? Leader選舉??

Leader在集群中是非常重要的一個角色,負責了整個事務的處理和調度,保證分布式數據一致性的關鍵所在。既然Leader在ZooKeeper集群中這么重要所以一定要保證集群在任何時候都有且僅有一個Leader存在。

如果集群中Leader不可用了,需要有一個機制來保證能從集群中找出一個最優的服務晉升為Leader繼續處理事務和調度等一系列職責。這個過程稱為Leader選舉。



? 選舉機制??

ZooKeeper選舉Leader依賴下列原則并遵循優先順序:

1、選舉投票必須在同一輪次中進行

如果Follower服務選舉輪次不同,不會采納投票。

2、數據最新的節點優先成為Leader

數據的新舊使用事務ID判定,事務ID越大認為節點數據約接近Leader的數據,自然應該成為Leader。

3、比較server.id,id值大的優先成為Leader

如果每個參與競選節點事務ID一樣,再使用server.id做比較。server.id是節點在集群中唯一的id,myid文件中配置。

不管是在集群啟動時選舉Leader還是集群運行中重新選舉Leader。集群中每個Follower角色服務都是以上面的條件作為基礎推選出合適的Leader,一旦出現某個節點被過半推選,那么該節點晉升為Leader。



? 過半原則??

ZooKeeper集群會有很多類型投票。Leader選舉投票;事務提議投票;這些投票依賴過半原則。就是說ZooKeeper認為投票結果超過了集群總數的一半,便可以安全的處理后續事務。

  • 事務提議投票

    假設有3個節點組成ZooKeeper集群,客戶端請求添加一個節點。Leader接到該事務請求后給所有Follower發起「創建節點」的提議投票。如果Leader收到了超過集群一半數量的反饋,繼續給所有Follower發起commit。此時Leader認為集群過半了,就算自己掛了集群也是安全可靠的。

  • Leader選舉投票

    假設有3個節點組成ZooKeeper集群,這時Leader掛了,需要投票選舉Leader。當相同投票結果過半后Leader選出。

  • 集群可用節點

    ZooKeeper集群中每個節點有自己的角色,對于集群可用性來說必須滿足過半原則。這個過半是指Leader角色 + Follower角色可用數大于集群中Leader角色 + Follower角色總數。
    假設有5個節點組成ZooKeeper集群,一個Leader、兩個Follower、兩個Observer。當掛掉兩個Follower或掛掉一個Leader和一個Follower時集群將不可用。因為Observer角色不參與任何形式的投票。

所謂過半原則算法是說票數 > 集群總節點數/2。其中集群總節點數/2的計算結果會向下取整。

在ZooKeeper源代碼QuorumMaj.java中實現了這個算法。下面代碼片段有所縮減。

public?boolean?containsQuorum(HashSet<Long>?set)?{
??/**?n是指集群總數?*/
??int?half?=?n?/?2;
??return?(set.size()?>?half);
}

回過頭我們看一下奇數和偶數集群在Leader選舉的結果

所以3節點和4節點組成的集群在ZooKeeper過半原則下都最多只能掛1節點,但是4比3要多浪費一個節點資源。

??場景實戰??

我們以兩個場景來了解集群不可用時Leader重新選舉的過程。



? 3節點集群重選Leader??

假設有3節點組成的集群,分別是server.1(Follower)、server.2(Leader)、server.3(Follower)。此時server.2不可用了。集群會產生以下變化:

1、集群不可用

因為Leader掛了,集群不可用于事務請求了。

2、狀態變更

所有Follower節點變更自身狀態為LOOKING,并且變更自身投票。投票內容就是自己節點的事務ID和server.id。我們以(事務ID, server.id)表示。

假設server.1的事務id是10,變更的自身投票就是(10, 1);server.3的事務id是8,變更的自身投票就是(8, 3)。

3、首輪投票

將變更的投票發給集群中所有的Follower節點。server.1將(10, 1)發給集群中所有Follower,包括它自己。server.3也一樣,將(8, 3)發給所有Follower。

所以server.1將收到(10, 1)和(8, 3)兩個投票,server.3將收到(8, 3)和(10, 1)兩個投票。

4、投票PK

每個Follower節點除了發起投票外,還接其他Follower發來的投票,并與自己的投票PK(比較兩個提議的事務ID以及server.id),PK結果決定是否要變更自身狀態并再次投票。

對于server.1來說收到(10, 1)和(8, 3)兩個投票,與自己變更的投票比較后沒有一個比自身投票(10, 1)要大的,所以server.1維持自身投票不變。

對于server.3來說收到(10, 1)和(8, 3)兩個投票,與自身變更的投票比較后認為server.1發來的投票要比自身的投票大,所以server.3會變更自身投票并將變更后的投票發給集群中所有Follower。

5、第二輪投票

server.3將自身投票變更為(10, 1)后再次將投票發給集群中所有Follower。

對于server.1來說在第二輪收到了(10, 1)投票,server.1經過PK后繼續維持不變。

對于server.3來說在第二輪收到了(10, 1)投票,因為server.3自身已變更為(10, 3)投票,所以本次也維持不變。

此時server.1和server.3在投票上達成一致。

6、投票接收桶

節點接收的投票存儲在一個接收桶里,每個Follower的投票結果在桶內只記錄一次。ZooKeeper源碼中接收桶用Map實現。

下面代碼片段是ZooKeeper定義的接收桶,以及向桶內寫入數據。Map.Key是Long類型,用來存儲投票來源節點的server.id,Vote則是對應節點的投票信息。節點收到投票后會更新這個接收桶,也就是說桶里存儲了所有Follower節點的投票并且僅存最后一次的投票結果。

HashMap<Long,?Vote>?recvset?=?new?HashMap<Long,?Vote>();
recvset.put(n.sid,?new?Vote(n.leader,?n.zxid,?n.electionEpoch,?n.peerEpoch));

7、統計投票

接收到投票后每次都會嘗試統計投票,投票統計過半后選舉成功。

投票統計的數據來源于投票接收桶里的投票數據,我們從頭描述這個場景,來看一下接收桶里的數據變化情況。

server.2掛了后,server.1和server.3發起第一輪投票。

server.1接收到來自server.1的(10, 1)投票和來自server.3的(8, 3)投票。

server.3同樣接收到來自server.1的(10, 1)投票和來自server.3的(8, 3)投票。此時server.1和server.3接收桶里的數據是這樣的:

server.3經過PK后認為server.1的選票比自己要大,所以變更了自己的投票并重新發起投票。

server.1收到了來自server.3的(10, 1)投票;server.3收到了來自sever.3的(10, 1)投票。此時server.1和server.3接收桶里的數據變成了這樣:

基于ZooKeeper過半原則:桶內投票選舉server.1作為Leader出現2次,滿足了過半?2 > 3/2?即 2>1。

最后sever.1節點晉升為Leader,server.3變更為Follower。



?集群擴容Leader啟動時機?

ZooKeeper集群擴容需要在zoo.cfg配置文件中加入新節點。擴容流程在ZooKeeper擴容中介紹。這里我們以3節點擴容到5節點時,Leader啟動時機做一個討論。

假設目前有3個節點組成集群,分別是server.1(Follower)、server.2(Leader)、server.3(Follower),假設集群中節點事務ID相同。配置文件如下。

server.1=localhost:2881:3881
server.2=localhost:2882:3882
server.3=localhost:2883:3883

1、新節點加入集群

集群中新增server.4和server.5兩個節點,首先修改server.4和server.5的zoo.cfg配置并啟動。節點4和5在啟動后會變更自身投票狀態,發起一輪Leader選舉投票。server.1、server.2、server.3收到投票后由于集群中已有選定Leader,所以會直接反饋server.4和server.5投票結果:server.2是Leader。server.4和server.5收到投票后基于過半原則認定server.2是Leader,自身便切換為Follower。

#節點server.1、server.2、server.3配置
server.1=localhost:2881:3881
server.2=localhost:2882:3882
server.3=localhost:2883:3883

#節點server.4、server.5配置
server.1=localhost:2881:3881
server.2=localhost:2882:3882
server.3=localhost:2883:3883
server.4=localhost:2884:3884
server.5=localhost:2885:3885

2、停止Leader

server.4和server.5的加入需要修改集群server.1、server.2、server.3的zoo.cfg配置并重啟。但是Leader節點何時重啟是有講究的,因為Leader重啟會導致集群中Follower發起Leader重新選舉。在server.4和server.5兩個新節點正常加入后,集群不會因為新節點加入變更Leader,所以目前server.2依然是Leader。

我們以一個錯誤的順序啟動,看一下集群會發生什么樣的變化。修改server.2zoo.cfg配置文件,增加server.4和server.5的配置并停止server.2服務。停止server.2后,Leader不存在了,集群中所有Follower會發起投票。當server.1和server.3發起投票時并不會將投票發給server.4和server.5,因為在server.1和server.3的集群配置中不包含server.4和server.5節點。相反,server.4和server.5會把選票發給集群中所有節點。也就是說對于server.1和server.3他們認為集群中只有3個節點。對于server.4和server.5他們認為集群中有5個節點。

根據過半原則,server.1和server.3很快會選出一個新Leader,我們這里假設server.3晉級成為了新Leader。但是我們沒有啟動server.2的情況下,因為投票不滿足過半原則,server.4和server.5會一直做投票選舉Leader的動作。截止到現在集群中節點狀態是這樣的:

3、啟動Leader

現在,我們啟動server.2。因為server.2zoo.cfg已經是server.1到serverv.5的全量配置,在server.2啟動后會發起選舉投票,同時serverv.4和serverv.5也在不斷的發起選舉投票。當server.2的選舉輪次和serverv.4與serverv.5選舉輪次對齊后,最終server.2會變更自己的狀態,認定server.5是Leaader。

意想不到的事情發生了,出現兩個Leader:

ZooKeeper集群擴容時,如果Leader節點最后啟動就可以避免這類問題發生,因為在Leader節點重啟前,所有的Follower節點zoo.cfg配置已經是相同的,他們基于同一個集群配置兩兩互聯,做投票選舉。

架構師小秘圈

聚集20萬架構師的小圈子

?

轉載于:https://www.cnblogs.com/bigben0123/p/10683091.html

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

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

相關文章

JVM初探:內存分配、GC原理與垃圾收集器

JVM內存的分配與回收大致可分為如下4個步驟: 何時分配 -> 怎樣分配 -> 何時回收 -> 怎樣回收. 除了在概念上可簡單認為new時分配外, 我們著重介紹后面的3個步驟: I. 怎樣分配- JVM內存分配策略 對象內存主要分配在新生代Eden區, 如果啟用了本地線程分配緩沖, 則優先在…

02 CSS

使用 table 進行布局存在缺陷&#xff0c;而一般的布局都會采用 DIVCSS 來進行布局。 Div 它是一個html 標簽&#xff0c;一個塊級元素(單獨顯示一行)。它單獨使用沒有任何意義&#xff0c;必須結合 CSS 來使用。它主要用于頁面的布局。 Span 它是一個 html 標簽&#xff0c;…

為什么要在密碼里加點“鹽”

鹽&#xff08;Salt&#xff09; 在密碼學中&#xff0c;是指通過在密碼任意固定位置插入特定的字符串&#xff0c;讓散列后的結果和使用原始密碼的散列結果不相符&#xff0c;這種過程稱之為“加鹽”。 以上這句話是維基百科上對于 Salt 的定義&#xff0c;但是僅憑這句話還是…

一致性哈希算法 應用

互聯網創業中大部分人都是草根創業&#xff0c;這個時候沒有強勁的服務器&#xff0c;也沒有錢去買很昂貴的海量數據庫。在這樣嚴峻的條件下&#xff0c;一批又一批的創業者從創業中獲得成 功&#xff0c;這個和當前的開源技術、海量數據架構有著必不可分的關系。比如我們使用m…

(9)How to take a picture of a black hole

https://www.ted.com/talks/katie_bouman_what_does_a_black_hole_look_like/transcript 00:13In the movie "Interstellar[??nt?r?stel?(r)]星際的," we get an up-close look at a supermassive black hole. Set against a backdrop of bright gas, the black…

單個節點的緩存容量達到上限 Hash算法一致性

場景 單個節點的緩存容量達到上限&#xff0c;無法繼續單點增加內存&#xff0c;如何解決&#xff1f; 單個節點支撐的QPS達到上限&#xff0c;如何解決&#xff1f; 初步方案 增加N個緩存節點&#xff0c;為了保證緩存數據的均勻&#xff0c;一般情況會采用對key值hash&…

java學習筆記11 (構造方法 this深探)

在開發中&#xff0c;經常需要在創建對象的同事明確對象對的屬性值&#xff0c;比如一個person對象創建的時候就應該有name和age 等屬性&#xff0c;那么如何做到在創建對象的同時給對象的屬性值初始化值呢&#xff1f; 這里介紹構造方法 1 構造方法沒有返回值類型&#xff0c;…

密碼中不能包含全角字符的正則表達式

String regex "^((?![^\\x00-\\xff]).)*$"; String str "aA"; System.out.println(str.matches(regex));

編程算法 - 將排序數組按絕對值大小排序 代碼(java)

一個含有多個元素的數組&#xff0c;有多種排序方式。它可以升序排列&#xff0c;可以降序排列&#xff0c;也可以像我們以前章節說過的&#xff0c;以波浪形方式排序&#xff0c;現在我們要看到的一種是絕對值排序。對于數組A,絕對值排序滿足以下條件&#xff1a;|A[i]| < …

QT Linux打包發布

Linux&#xff1a; 1、用Release編譯&#xff1b; 2、把可執行文件(如paike)放入新建目錄中; 3、當前目錄下編寫腳本copyDependency.sh&#xff0c;把動態鏈接庫導入當前目錄&#xff1b; #!/bin/shexe"paike" #發布的程序名稱destination"/home/paike"…

CRM公海自動回收規則

企微云CRM操作指南 – 道一云|企微https://wbg.do1.com.cn/xueyuan/2568.html 銷售云 - 美洽 - 連接客戶&#xff0c;親密無間https://meiqia.com/sales-cloud 轉載于:https://www.cnblogs.com/rgqancy/p/10695466.html

三分鐘看懂一致性哈希算法

一致性哈希算法&#xff0c;作為分布式計算的數據分配參考&#xff0c;比傳統的取模&#xff0c;劃段都好很多。 在電信計費中&#xff0c;可以作為多臺消息接口機和在線計費主機的分配算法&#xff0c;根據session_id來分配&#xff0c;這樣當計費主機動態伸縮的時候&#xf…

數據結構09圖

第七章 圖 Graph 7.1 圖的定義和術語 頂點 Vertex V 是頂點的有窮非空集合&#xff0c;頂點數 |V| n VR 兩個頂點之間關系的集合&#xff0c;邊數 |VR| e 有向圖 Digraph <v, w> Arc v Tail / Inital node w Head / Terminal node 無向圖 Undigraph <v, w> 必…

JVM調優-GC參數

一、Throughput收集器(吞吐量) -XX:UseParallelGC -XX:UseParallelOldGC *參數調整&#xff1a;通過調整堆大小&#xff0c;減少GC停頓時間&#xff0c;增大吞吐量 增強堆大小可以減少Full GC頻率&#xff0c;但卻會增加停頓時間 1.手動調整 -Xmn -Xms -XX:NewRatioN 手動指…

aspnetcore源碼學習(一)

---恢復內容開始--- 筆者從事netcore相關項目開發已經大半年了&#xff0c;從netcore 1.0到現在3.0大概經過了3年左右的時間&#xff0c;記得netcore剛出來的時候國內相關的學習資料缺乏&#xff0c;限制于外語不大熟練的限制國外的相關書籍看起來相當吃力&#xff0c;于是在當…

評估一個垃圾收集(GC)

在實踐中我們發現對于大多數的應用領域&#xff0c;評估一個垃圾收集(GC)算法如何根據如下兩個標準&#xff1a; 吞吐量越高算法越好暫停時間越短算法越好 首先讓我們來明確垃圾收集(GC)中的兩個術語:吞吐量(throughput)和暫停時間(pause times)。 JVM在專門的線程(GC threads…

python數據分析常用包之Scipy

Scipy轉載于:https://www.cnblogs.com/jacky912/p/10697853.html

docker容器狀態跟蹤及疑惑

一、 1 def status_test():2 container client.containers.create("comp")3 print ("create: ", container.status)4 container.start()5 print ("start: ", container.status)6 container.pause()7 print ("paus…

CAP和BASE理論

幾個名詞解釋&#xff1a; 網絡分區&#xff1a;俗稱“腦裂”。當網絡發生異常情況&#xff0c;導致分布式系統中部分節點之間的網絡延時不斷變大&#xff0c;最終導致組成分布式系統的所有節點中&#xff0c;只有部分節點之間能夠進行正常通信&#xff0c;而另一些節點則不能…

Mysql案例5:取得平均薪資最高的部門的部門名稱

一、要求&#xff1a;查詢平均薪水最高部門的部門編號 二、背景&#xff1a;當前數據庫有employee表和department表&#xff0c;數據分別如下&#xff1a; employee表&#xff1a; department表&#xff1a; 三、難點&#xff1a; 1、需要考慮最高平均薪資可能在多個部門同時出…