MongoDB副本集主節點的選舉過程

MongoDB的複製集具備自動容忍部分節點宕機的功能,在複製集出現問題時時,會觸發選舉相關的過程,完成主從節點自動切換。每一個複製集成員都會在後臺運行與複製集全部節點的心跳線程,在兩種狀況下會觸發狀態檢測過程:ide

  1. 複製集成員心跳檢測結果發生變化,好比某個節點掛了或者新增節點;
  2. 超過4s沒有執行狀態檢測過程。在狀態檢測過程大體包含如下步驟:

(1)檢測自身是否處於選舉過程,若是是,退出本次過程。
(2)維護一個主節點的備用列表,列表中全部節點均可能被選舉爲主節點,每一個節點都會檢測自身以及全局條件是否知足:
a. 是否看見覆制集中有Majority在線。
b. 自身priority大於0。
c. 自身不爲arbiter。
d. 自身opTime不能落後於最新節點10s以上。
e. 自身存儲的集羣程序按信息爲最新。
若是全部條件知足,則將自身添加到主節點備用列表中,不然,將自身從列表中移除。線程

檢測如下條件,若都知足,將主節點降爲從節點(若是要降級的主節點是自身,直接調用降級方法,若是不爲自身,調用replSetStepDown命令將複製集主節點降級爲從節點:
    a. 集羣中主節點存在。
    b. "主節點的備用列表」中存在比當前的主節點priority更高的節點。
    c. "主節點的備用列表」中priority最高的節點,其opTime要比其餘全部節點最新的opTime落後10s之內。
    d. 檢測自身是否爲主,若爲主,且自身沒法看見覆制集的Majority在線,將自身降級爲從。
    e. 若是看不見集羣中有主節點存在,檢測自身是否在」主節點的備用列表」,若不在,打印log並退出此流程。
    f. 若自身在」主節點的備用列表」中,開始判斷自身能否向複製集中發送選舉自身爲主節點的通知,判斷過程包含:
         1> 自身是否能夠看見覆制集中的Majority在線。
         2>自身是否在」主節點的備用列表」。

若條件知足,則設置」自身已經在選舉過程當中」標識位爲true,並進入」選舉自身爲主節點」方法。
方法中會驗證自身是否知足如下條件:
a. 此線程拿到了線程鎖。
b. 此節點沒有被配置slaveDelay選項或者配置的slaveDelay爲0。
c. 此節點沒有被配置爲arbiter。
若知足,則調用環境檢測,若如下條件被觸發,則不發送"選舉我爲主節點」投票:
1> 當前時間小於steppedDown的結束凍結時間(爲執行steppedDown時的時間+凍結設定時間,內部調用爲60s)。
2> 本身的opTime不是全部節點最新的。
3> 如有節點opTime比本身新,直接退出此流程。
若是其餘最新的節點最多與本身同樣新,每有一個這樣的節點,隨機sleep一段時間,以後繼續判斷。
a. 本身上線5分鐘內且複製集中不是全部節點在線。
b. 如無其餘問題,嘗試獲取本身進行投票時的票數,在此過程當中,會判斷本身在30s內是否進行過投票,如進行過,直接退出整個過程。
通過以上種種複雜的檢測,終於能夠向複製集發送」選舉我爲主節點」的投票。
發送以後,會接收來自全部節點的投票,若得票數小於等於一半,不將本身變爲主節點,若超過一半,設置本身爲主節點。
投票結束後,設置」自身已經在選舉過程當中」標識位爲false。
能夠看到,上面的判斷邏輯有一些是重複判斷,不過不影響最終結果,可能與判斷邏輯較爲複雜有關係,在每一個決定以前都要驗證全部條件是否知足,防止有條件被漏掉。
在複製集中的節點收到其餘節點發送的」選舉我爲主節點」投票信息時,會有如下的判斷:
a. 若自身存儲的複製集配置版本太低,不投票。
b. 若發起請求的節點存儲的複製集配置版本太低,投反對票。
c. 若是自身所在的複製集沒有發起投票的節點,投反對票。
d. 複製集中存在主節點,投反對票。
可參與選舉的節點中有priority高於請求爲主的節點存在時,投反對票。
若是全部條件經過,獲取自身的投票數(一樣會判斷自身在30s內是否參加過投票,若參加過,再也不投票),投出票數。
須要說一下的是,一個反對會將最終票數減10000,即在絕大多數狀況下,只要有節點反對,請求的節點就不能成爲主節點。
選舉過程很複雜,實際使用中總結爲兩點:
通常狀況下須要5s左右進行選主。
若是新選舉出的主節點立馬掛掉,至少須要30s時間從新選主。code

相關文章
相關標籤/搜索