分佈式計算原理之分佈式協調與同步(1)——分佈式選舉

1:分佈式選舉的概念

一般來說,集羣有兩個或兩個以上的服務器組件而成,其中,每個服務器都是集羣中的一個節點。對於一個節點來說,多個節點是如何做到協同工作?比如數據庫集羣,如何保證數據庫寫入集羣在每個節點上都是一致的呢?

即:在衆多節點中,選舉一個leader來管理和調度其他節點,而“選舉”的過程在分佈式領域中,就叫分佈式選舉。

2:爲什麼要有分佈式選舉

leader節點,也就是主節點,在一個分佈式集羣中負責對其他節點的協調和管理,也就是說,其他節點都必須聽從主節點的安排。主節點的存在,就可以保證其他節點的有序運行,以及數據庫集羣中的寫入數據在每個節點上的一致性。這裏的一致性是指數據在每個集羣節點中都是一樣的。但是,如果主節點故障了,集羣也會出現混亂,可能導致每個節點上的數據會不一致。
總結來說,選舉的作用就是選出一個主節點,由它來協調和管理其他節點,以保證集羣有序運行和節點間數據的一致性

3:分佈式選舉算法

目前常見的選主方法主要有以下幾種:

  1. 基於序號選舉的算法,比如,Bully 算法
  2. 多數派算法,比如,Raft 算法、ZAB 算法

3.1:Bully 算法

選舉原則:Bully 算法機制比較簡單,選舉原則是“長者”爲大,即在所有存活的節點中,選取 ID 最大的節點作爲主節點。

在 Bully 算法中,節點的角色有兩種:普通節點和主節點。初始化時,所有節點都是平等的,都是普通節點,並且都有成爲主的權利。但是,當選主成功後,有且僅有一個節點成爲主節點,其他所有節點都是普通節點。當且僅當主節點故障或與其他節點失去聯繫後,纔會重新選主。

Bully 算法在選舉過程中,需要用到以下 3 種消息:

  • Election 消息,用於發起選舉;
  • Alive 消息,對 Election 消息的應答;
  • Victory 消息,競選成功的主節點向其他節點發送的宣誓主權的消息。

具體選舉過程如下:

  1. 集羣中每個節點判斷自己的 ID 是否爲當前活着的節點中 ID 最大的,如果是,則直接向其他節點發送 Victory 消息,宣誓自己的主權;
  2. 如果自己不是當前活着的節點中 ID 最大的,則向比自己 ID 大的所有節點發送 Election 消息,並等待其他節點的回覆;
  3. 若在給定的時間範圍內,本節點沒有收到其他節點回復的 Alive 消息,則認爲自己成爲主節點,並向其他節點發送 Victory 消息,宣誓自己成爲主節點;若接收到來自比自己 ID 大的節點的 Alive 消息,則等待其他節點發送 Victory 消息;
  4. 若本節點收到比自己 ID 小的節點發送的 Election 消息,則回覆一個 Alive 消息,告知其他節點,我比你大,重新選舉。

在這裏插入圖片描述
優缺點總結

優點:Bully算法的選舉機制比較簡單,存活的節點大會的ID最大誰就是主節點,這種算法的有點是比較簡單,選舉速度快,簡單容易實現。
缺點:每個節點需要有全局的節點信息,因此額外信息存儲比較多,其次,任意一個比當前主節點ID大的新節點或節點故障恢復後,都可能重新觸發選舉,成爲新的主節點,如果該節點頻繁退出、加入集羣,就是導致頻繁切主。

3.2 :Raft 算法

Bully算法簡單且暴力,相比之下,Raft 算法是典型的多數派投票選舉算法,其選舉機制與日常生活中的投票機制類似,簡單地說就是“少數服從多數”,獲得投票最多的節點成爲主。

採用 Raft 算法選舉,集羣節點的角色有 3 種:

  • Leader,即主節點,同一時刻只有一個 Leader,負責協調和管理其他節點
  • Candidate,即候選者,每一個節點都可以成爲 Candidate,節點在該角色下才可以被選爲新的 Leader;
  • Follower,Leader 的跟隨者,不可以發起選舉。

Raft 選舉的流程,可以分爲以下幾步:

  1. 初始化時,所有節點均爲 Follower 狀態。
  2. 開始選主時,所有節點的狀態由 Follower 轉化爲 Candidate,並向其他節點發送選舉請求。
  3. 其他節點根據接收到的選舉請求的先後順序,回覆是否同意成爲主。這裏需要注意的是,在每一輪選舉中,一個節點只能投出一張票。
  4. 若發起選舉請求的節點獲得超過一半的投票,則成爲主節點,其狀態轉化爲 Leader,其他節點的狀態則由 Candidate 降爲 Follower。Leader 節點與 Follower 節點之間會定期發送心跳包,以檢測主節點是否活着。
  5. 當 Leader 節點的任期到了,即發現其他服務器開始下一輪選主週期時,Leader 節點的狀態由 Leader 降級爲 Follower,進入新一輪選主。

節點的狀態遷移如下所示(圖中的 term 指的是選舉週期):
在這裏插入圖片描述
每一輪選舉,每個節點只能投一次票。 Raft 算法中,選主是週期進行的,也就是隔一段時間重新選舉,但也有例外的時候,如果主節點故障,會立馬發起選舉,重新選出一個主節點。

優缺點總結
優點:Raft 算法具有選舉速度快、算法複雜度低、易於實現的優點,該算法選舉穩定性比 Bully 算法好,這是因爲當有新節點加入或節點故障恢復後,會觸發選主,但不一定會真正切主,除非新節點或故障後恢復的節點獲得投票數過半,纔會導致切主。;
加粗樣式:缺點是,它要求系統內每個節點都可以相互通信,且需要獲得過半的投票數才能選主成功,因此通信量大。

3.3:ZAB 算法

ZAB(ZooKeeper Atomic Broadcast)選舉算法是爲 ZooKeeper 實現分佈式協調功能而設計的。相較於 Raft 算法的投票機制,ZAB 算法增加了通過節點 ID 和數據 ID 作爲參考進行選主,節點 ID 和數據 ID 越大,表示數據越新,優先成爲主

相比較於 Raft 算法,ZAB 算法儘可能保證數據的最新性,所以,ZAB 算法可以說是對 Raft 算法的改進。

使用 ZAB 算法選舉時,集羣中每個節點擁有 3 種角色:

  1. Leader,主節點;
  2. Follower,跟隨者節點;
  3. Observer,觀察者,無投票權。

選舉過程中,集羣中的節點擁有 4 個狀態:

  1. Looking 狀態,即選舉狀態。當節點處於該狀態時,它會認爲當前集羣中沒有 Leader,因此自己進入選舉狀態。
  2. Leading 狀態,即領導者狀態,表示已經選出主,且當前節點爲 Leader。
  3. Following 狀態,即跟隨者狀態,集羣中已經選出主後,其他非主節點狀態更新爲 Following,表示對 Leader 的追隨。
  4. Observing 狀態,即觀察者狀態,表示當前節點爲 Observer,持觀望態度,沒有投票權和選舉權。

投票過程中,每個節點都有一個唯一的三元組 (server_id, server_zxID, epoch),其中 server_id 表示本節點的唯一 ID;server_zxID 表示本節點存放的數據 ID,數據 ID 越大表示數據越新,選舉權重越大;epoch 表示當前選取輪數,一般用邏輯時鐘表示。

ZAB 選舉算法的核心與Raft類似,即:“少數服從多數,ID 大的節點優先成爲主”,選舉過程中通過 (vote_id, vote_zxID) 來表明投票給哪個節點,其中 vote_id 表示被投票節點的 ID,vote_zxID 表示被投票節點的服務器 zxID。ZAB 算法選主的原則是:server_zxID 最大者成爲 Leader;若 server_zxID 相同,則 server_id 最大者成爲 Leader。

以 3 個 Server 的集羣爲例,每個 Server 代表一個節點,說明 ZAB 選主的過程。

第一步:當系統啓動時,3個服務器當前投票均爲第一輪投票,即epoch=1,且 zxID 均爲 0。此時每個服務器都推選自己,並將選票信息 <epoch, vote_id, vote_zxID> 廣播出去。
在這裏插入圖片描述
第二步:根據判斷規則,由於 3 個 Server 的 epoch、zxID 都相同,因此比較 server_id,較大者即爲推選對象,因此 Server 1 和 Server 2 將 vote_id 改爲 3,更新自己的投票箱並重新廣播自己的投票。
在這裏插入圖片描述
第三步:此時系統內所有服務器都推選了 Server 3,因此 Server 3 當選 Leader,處於 Leading 狀態,向其他服務器發送心跳包並維護連接;Server1 和 Server2 處於 Following 狀態。
在這裏插入圖片描述
優缺點總結:

優點:ZAB 算法性能高,對系統無特殊要求,該算法選舉穩定性比較好,當有新節點加入或節點故障恢復後,會觸發選主,但不一定會真正切主,除非新節點或故障後恢復的節點數據 ID 和節點 ID 最大,且獲得投票數過半,纔會導致切主。

缺點:ZAB算法採用廣播方式發送信息,若節點中有 n 個節點,每個節點同時廣播,則集羣中信息量爲 n*(n-1) 個消息,容易出現廣播風暴;且除了投票,還增加了對比節點 ID 和數據 ID,這就意味着還需要知道所有節點的 ID 和數據 ID,所以選舉時間相對較長。

4:三種算法對比總結

在這裏插入圖片描述

5:相關延伸問題

1. 爲什麼"多數派"選主算法通常採用基數節點,而不是偶數節點?

多數派選主算法的核心是少數服從多數,獲得投票多的節點勝出。想象一下,如果現在採用偶數節點集羣,當兩個節點均獲得一半投票時,無法選主,必須重新投票,但即使重新投票選舉,兩個節點擁有相同投票數的概率也會很大。因此,多數派選主算法通常採用奇數節點。

2.分佈式選舉和一致性的關係是什麼?
分佈式選舉是爲了保證數據一致性,在集羣中存在多個節點提供服務,以mysql數據庫集羣爲例,如果每個節點都可以寫數據,這樣容易造成數據的不一致,所以需要選舉一個leader,往leader節點中寫數據,然後同步到follower節點中。這樣就能更好的保證一致性
。所以mysq集羣主節點寫入數據,從節點提供讀功能,即主從架構

最後總結

在這裏插入圖片描述

參考文獻

  1. George Coulouris:《分佈式系統:概念與設計》
  2. 聶鵬程:《分佈式技術原理與算法解析》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章