分布式系統一致性問題和Raft一致性算法


一致性問題

一致性算法是用來解決一致性問題的,那么什么是一致性問題呢? 在分布式系統中,一致性問題(consensus problem)是指對於一組服務器,給定一組操作,我們需要一個協議使得最后它們的結果達成一致. 更詳細的解釋就是,當其中某個服務器收到客戶端的一組指令時,它必須與其它服務器交流以保證所有的服務器都是以同樣的順序收到同樣的指令,這樣的話所有的服務器會產生一致的結果,看起來就像是一台機器一樣.

實際生產中一致性算法需要具備以下屬性:

  • safety:即不管怎樣都不會返回錯誤的結果
  • available:只要大部分的機器正常,就仍然可以工作.比如五台機器的集群允許最多兩台機器壞掉.
  • 不依賴時間來確保一致,即系統是異步的.
  • 一般情況下,運行時間由大多數的機器決定,不會因為有少部分慢的機器而影響總體效率.

為什么要解決一致性問題?

我們可以說一個分布式系統可靠性達到99.99...%,但不能說它達到了100%, 為什么? 就是因為一致性問題是無法徹底解決的. 以下四個分布式系統中的問題都與一致性問題有關:

  1. reliable multicast 可靠組播
  2. membership protocal (failuer detector) 集群中成員的管理
  3. leader election 選舉算法
  4. mutual exclution 互斥,例如資源的獨占和分配

Raft一致性算法

前面我介紹了教科書上的一些選舉算法, 它們也是屬於一致性算法,即最后所有服務器所認為的leader都是一致的. 現在實際應用中主流的一致性算法有兩個Paxos 和 Raft. Zookeeper 就是選用的Paxos, 而etcd使用的Raft. 作為一名Go愛好者,我先來講一下Raft吧.

Raft是因為Paxos太難懂太難以實現而提出的,目的是在可靠性不輸於Paxos的情況下,盡可能的簡單易懂. 但是Raft的論文 In Search of an Understandable Consensus Algorithm還是有18頁,我要比它更簡單易懂.

Raft把一致性問題分解成為三個小問題:

  1. leader election 選舉
  2. log replication 日志復制,同步
  3. safety 安全性

基本概念

每個Server有三個狀態: leader, follower, candidate

  • follower: 不發request而只會回復leader和candidate的request.
  • leader: 處理client發過來的請求
  • candidate: leader的候選人

Raft把時間分為terms. 每一個term開始時都進行一次選舉. 每一個term里最多有一個leader, 或者沒有leader.

RPC實現

算法需要兩種RPC, RequestVote RPC:由candidates在選舉過程中發起,當另外一個server收到這個RPC之后, 只有當對方term和log都至少和自己的一樣新的時候才會投贊成票,收到多數贊成票的candidate會當選leader.

AppendEntries RPC 由leader發起用來分發日志, 強迫follwer的log和自己一致.

Leader election

如果一個follower在election timeout的時間里沒有收到leader的信息,就進入新的term,轉成candidate,給自己投票,發起選舉 RequestVote RPC. 這個狀態持續到發生下面三個中的任意事件:

  1. 它贏得選舉
  2. 另外有Server獲得選舉
  3. 1個term過去了,還是沒有選舉結果

為什么會有3這個情況呢,就是當如果大家同時發起選舉,都投給自己,那就沒有Server能夠得到多數選票了,這個時候就要進入下一個term,再選一次. 為了避免這個情況持續發生,每個Server的election time被隨機的設成不同的值,所以先timeout的就可以先發起下一次選舉.

Log replication

選好leader之后就可以分發log啦.

每一個log都有一個log index 和 term number. 當大多數的follower都復制好這個log時,就說這個log是committed,可以執行了. Leader 記住已經commit的最大log index, 用它來分發下一個 AppendEntries RPC. 這個和TCP里段的編號的作用是一樣的.

當一個leader重新選出來時,它的log和follower的log可能不一致,那么它會強制所有的follower都和自己的log一致.首先leader要找到和follower之間的最大的編號一致的log,然后覆蓋掉那之后的log.

Safety

但是到目前為止仍然不能保證安全性.比如說, 當leader在commit log時, 某follower掉線了,然后這個follower后來被選為leader,它會覆蓋掉現在follwer那些已經committed log, 由於這些log是已經執行過的,所以結果不同的機器就執行不同的指令. 在選舉過程中,再加多一個限制就可以防止這種情況發生, 即:

Leader completeness property: 
對於任意一個term, leader都要包含所以在之前term里committed的logs.

這樣就是完整的Raft算法了.

注:圖片都來自Paper In Search of an Understandable Consensus Algorithm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM