一、zookeeper集群
配置多個實例共同構成一個集群對外提供服務以達到水平擴展的目的,每個服務器上的數據是相同的,每一個服務器均可以對外提供讀和寫的服務,這點和redis是相同的,即對客戶端來講每個服務器都是平等的。
這篇主要分析leader的選擇機制,zookeeper提供了三種方式:
- LeaderElection
- AuthFastLeaderElection
- FastLeaderElection (最新默認)
默認的算法是FastLeaderElection,所以這篇主要分析它的選舉機制。
二、選舉流程簡述
目前有5臺服務器,每臺服務器均沒有數據,它們的編號分別是1,2,3,4,5,按編號依次啟動,它們的選擇舉過程如下:
- 服務器1啟動,給自己投票,然后發投票信息,由于其它機器還沒有啟動所以它收不到反饋信息,服務器1的狀態一直屬于Looking(選舉狀態)。
- 服務器2啟動,給自己投票,同時與之前啟動的服務器1交換結果,由于服務器2的編號大所以服務器2勝出,但此時投票數沒有大于半數,所以兩個服務器的狀態依然是LOOKING。
- 服務器3啟動,給自己投票,同時與之前啟動的服務器1,2交換信息,由于服務器3的編號最大所以服務器3勝出,此時投票數正好大于半數,所以服務器3成為領導者,服務器1,2成為小弟。
- 服務器4啟動,給自己投票,同時與之前啟動的服務器1,2,3交換信息,盡管服務器4的編號大,但之前服務器3已經勝出,所以服務器4只能成為小弟。
- 服務器5啟動,后面的邏輯同服務器4成為小弟。
三、選擇機制中的概念
1、Serverid:服務器ID
比如有三臺服務器,編號分別是1,2,3。
編號越大在選擇算法中的權重越大。
2、Zxid:數據ID
服務器中存放的最大數據ID.
值越大說明數據越新,在選舉算法中數據越新權重越大。
3、Epoch:邏輯時鐘
或者叫投票的次數,同一輪投票過程中的邏輯時鐘值是相同的。每投完一次票這個數據就會增加,然后與接收到的其它服務器返回的投票信息中的數值相比,根據不同的值做出不同的判斷。
4、Server狀態:選舉狀態
- LOOKING,競選狀態。
- FOLLOWING,隨從狀態,同步leader狀態,參與投票。
- OBSERVING,觀察狀態,同步leader狀態,不參與投票。
- LEADING,領導者狀態。
四、選舉消息內容
在投票完成后,需要將投票信息發送給集群中的所有服務器,它包含如下內容。
- 服務器ID
- 數據ID
- 邏輯時鐘
- 選舉狀態
五、選舉流程圖
因為每個服務器都是獨立的,在啟動時均從初始狀態開始參與選舉,下面是簡易流程圖。
六、選舉狀態圖
描述Leader選擇過程中的狀態變化,這是假設全部實例中均沒有數據,假設服務器啟動順序分別為:A,B,C。
七、判斷是否已經勝出
默認是采用投票數大于半數則勝出的邏輯。
八、選舉流程詳述
一、首先開始選舉階段,每個Server讀取自身的zxid。
二、發送投票信息
a、首先,每個Server第一輪都會投票給自己。
b、投票信息包含 :所選舉leader的Serverid,Zxid,Epoch。Epoch會隨著選舉輪數的增加而遞增。
三、接收投票信息
1、如果服務器B接收到服務器A的數據(服務器A處于選舉狀態(LOOKING 狀態)
1)首先,判斷邏輯時鐘值:
a)如果發送過來的邏輯時鐘Epoch大于目前的邏輯時鐘。首先,更新本邏輯時鐘Epoch,同時清空本輪邏輯時鐘收集到的來自其他server的選舉數據。然后,判斷是否需要更新當前自己的選舉leader Serverid。判斷規則rules judging:保存的zxid最大值和leader Serverid來進行判斷的。先看數據zxid,數據zxid大者勝出;其次再判斷leader Serverid,leader Serverid大者勝出;然后再將自身最新的選舉結果(也就是上面提到的三種數據(leader Serverid,Zxid,Epoch)廣播給其他server)
b)如果發送過來的邏輯時鐘Epoch小于目前的邏輯時鐘。說明對方server在一個相對較早的Epoch中,這里只需要將本機的三種數據(leader Serverid,Zxid,Epoch)發送過去就行。
c)如果發送過來的邏輯時鐘Epoch等于目前的邏輯時鐘。再根據上述判斷規則rules judging來選舉leader ,然后再將自身最新的選舉結果(也就是上面提到的三種數據(leader Serverid,Zxid,Epoch)廣播給其他server)。
2)其次,判斷服務器是不是已經收集到了所有服務器的選舉狀態:若是,根據選舉結果設置自己的角色(FOLLOWING還是LEADER),退出選舉過程就是了。
最后,若沒有收到沒有收集到所有服務器的選舉狀態:也可以判斷一下根據以上過程之后最新的選舉leader是不是得到了超過半數以上服務器的支持,如果是,那么嘗試在200ms內接收一下數據,如果沒有新的數據到來,說明大家都已經默認了這個結果,同樣也設置角色退出選舉過程。
2、 如果所接收服務器A處在其它狀態(FOLLOWING或者LEADING)。
a)邏輯時鐘Epoch等于目前的邏輯時鐘,將該數據保存到recvset。此時Server已經處于LEADING狀態,說明此時這個server已經投票選出結果。若此時這個接收服務器宣稱自己是leader, 那么將判斷是不是有半數以上的服務器選舉它,如果是則設置選舉狀態退出選舉過程。
b) 否則這是一條與當前邏輯時鐘不符合的消息,那么說明在另一個選舉過程中已經有了選舉結果,于是將該選舉結果加入到outofelection集合中,再根據outofelection來判斷是否可以結束選舉,如果可以也是保存邏輯時鐘,設置選舉狀態,退出選舉過程。