Zookeeper源碼分析之leader選舉流程分析

1.爲什麼要進行leader選舉?

衆所周知,Zookeeper是一款分佈式協調調度框架。生來就是爲了解決分佈式中有關問題的。而今天要說的leader選舉,能幫我們解決分佈式環境下的數據一致性問題。在集羣模式下,Zookeeper集羣的節點分爲leader,follower,observer三種角色。

leader:集羣中的決策者,只有產生一個,用來處理客戶端的所有事務性請求,如create,delete等。

follower:leader的跟隨者,可以有多個,只用來處理客戶端的非事務性請求,如getChildren,isExists等。

observer:觀察者,用來轉發事務的請求,與follower區別不到,但是其不參與leader選舉。

集羣中,leader和follower分工明確,各司其職,讓我們在分佈式環境下的數據一致性得到了很好的保障。

2.什麼時候會進行leader選舉?

先了解一下各節點在集羣的狀態變化。在集羣中,節點的狀態有4種,分別是:looking,following,leading,observing。在沒有選舉出leader之前,每個節點的最初狀態都是looking。還有一種情況是,當一個正常運行的集羣突然由於網絡等原因導致leader節點掛掉或者彼此之前無法通訊,此時會重新進行選舉,所有的節點又會恢復到looking狀態。當leader節點選舉出來之後,所有的節點就會被更新成leading或者following。leader選舉只會發生在looking狀態之前,也就是集羣啓動時,或者leader節點掛掉後這兩種情況。

3.leader選舉的大致流程

  • 先了解一下下面幾個概念:

myid:每臺服務器的id標識,在zoo.cfg配置集羣模式會有體現,id越大,能力越強,成爲leader的機率越大;

zxid:每臺服務器標識數據的事務id,事務id越大,表示當前節點的數據越新,能力越強,成爲leader的機率越大;

electionEpoch:邏輯時鐘,用來判斷各個服務器之間是否是同一輪leader選舉,每進行一輪,會進行自增;

peerEpoch:每臺服務器給出投票中被推舉爲leader的邏輯時鐘,epoch越大,成爲leader的機率越大;

這幾個值,都會成爲選舉的重要參數,在選票PK時,會進行優選級的比較,最終選出最優秀的機器,推薦爲leader。

  • leader選舉流程

1.在集羣剛開始啓動時,每個節點都會生成一個選票,默認最開始都是會推選自己爲leader;

2.各服務器間通過建立socket連接,進行相互通訊,用來發送和接收選票,當然,這一步在集羣啓動的時候就會建立;此處有一個連接建立規則,只允許myid大的一方連接小的一方,如果小的連到了大的一方,會斷開連接,轉過身大的一方會主動與小的一方建立連接。這樣做的目的是避免建立重複連接,解釋不必要的網絡IO開銷。

3.各個服務器通過選票發送器會將自己的選票發送其他的節點上;

4.while循環進行獲取,然後逐個跟自己的選票進行PK,此處有3處判斷;

  • 收到的選票的邏輯時鐘大於當前節點,說明當前節點的選舉已經落後,那麼立即將當前節點的邏輯時鐘更新爲最新,清空自己的投票箱(收到的選票),然後再跟當前選票進行PK,選出最優者,更新自己的選票;
  • 收到的選票的邏輯時鐘小於當前節點,說明收到的投票不是最新,則直接忽略,不做任何操作;
  • 兩者的選票是同一屆選舉,此時進行PK,PK的優選條件如下:
  1. 當前peerEpoch>currEpoch,那麼收到的選票中的節點更優;
  2. 如果選舉的epoch一致,則比較zxid,zxid越大,則更優秀;
  3. 如果zxid相等,則比較myid,id越大則表示更優秀;
  • PK完後,把自己的選票更新成最新,然後通過選票發送器發送給其他的節點;

5.統計投票箱,判斷當前被推選爲leader的節點,是否已經有超過半數的節點投給了它,這就是zk中的過半機制;

6.當選舉出leader後,每臺機器會更改自己的節點狀態,成爲leader的節點更新爲leading,其餘爲following。

4.leader選舉示例分析

Server3,Server4,Server5的myid分別爲3,4,5

Server3,Server4,Server5的zxid分別爲9,8,8

1.首先Server3,Server4,Server5各自投自己一票,推選自己爲leader,然後將選票發送給其他節點;

Server3收到的選票:(4,8)(5,8)--->自己的選票(3,9)

Server4收到的選票:(3,9)(5,8)--->自己的選票(4,8)

Server5收到的選票:(3,9)(4,8)--->自己的選票(5,8)

2.選票PK

Server3:3與4比較,3zxid大,獲勝,3與5比較,3zxid大,獲勝,還是最初的選票(3,9);

Server4:4與3比較,3zxid大,獲勝,3與5比較,3zxid大,獲勝,變更選票爲(3,9);

Server5:5與3比較,3zxid大,獲勝,3與4比較,3zxid大,獲勝,變更選票爲(3,9);

3.將新的投票發送給其他的服務器節點;

Server3收到的選票:(3,9)(3,9)--->自己的選票(3,9)

Server4收到的選票:(3,9)(3,9)--->自己的選票(3,9)

Server5收到的選票:(3,9)(3,9)--->自己的選票(3,9)

4.統計投票箱,很明顯此時選中Server3的投票已過半數,那麼leader已選出;

5.更新狀態,Server3更新爲leading狀態,Server4和Server5更新爲following狀態,該集羣可以正常對外提供服務。

leader選舉的大致流程就介紹到這了,這裏着重介紹了在集羣啓動時的leader選舉,運行期間leader掛掉後的leader選舉跟這個流程大同小異,下一篇文章我將着重從源碼介紹leader選舉的實現原理,敬請期待!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章