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的優選條件如下:
- 當前peerEpoch>currEpoch,那麼收到的選票中的節點更優;
- 如果選舉的epoch一致,則比較zxid,zxid越大,則更優秀;
- 如果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選舉的實現原理,敬請期待!