一致性算法RAFT詳解

原帖地址:http://www.solinx.co/archives/415?utm_source=tuicool&utm_medium=referral
一致性算法Raft詳解背景
  熟悉或瞭解分佈性系統的開發者都字段一致性算法的重要性,Paxos一致性算法從90年提出到如今已經有二十幾年了,而Paxos流程太過於繁雜實現起來也比較複雜,可能也是覺得過於複雜 如今我據說過比較出名使用到Paxos的也就只是Chubby、libpaxos,搜了下發現Keyspace、BerkeleyDB數據庫中也使用了該算法做爲數據的一致性同步,雖然如今很普遍使用的Zookeeper也是基於Paxos算法來實現,可是Zookeeper使用的ZAB(Zookeeper Atomic Broadcast)協議對Paxos進行了不少的改進與優化,算法複雜我想會是制約他發展的一個重要緣由;說了這麼多隻是爲了要引出本篇文章的主角Raft一致性算法,沒錯Raft就是在這個背景下誕生的,文章開頭也說到了Paxos最大的問題就是複雜,Raft一致性算法就是比Paxos簡單又能實現Paxos所解決的問題的一致性算法。
  Raft是斯坦福的Diego Ongaro、John Ousterhout兩我的以易懂(Understandability)爲目標設計的一致性算法,在2013年發佈了論文:《In Search of an Understandable Consensus Algorithm》從2013年發佈到如今不過只有兩年,到如今已經有了十多種語言的Raft算法實現框架,較爲出名的有etcd,Google的Kubernetes也是用了etcd做爲他的服務發現框架;因而可知易懂性是多麼的重要。
Raft概述
  與Paxos不一樣Raft強調的是易懂(Understandability),Raft和Paxos同樣只要保證n/2+1節點正常就可以提供服務;衆所周知但問題較爲複雜時能夠把問題分解爲幾個小問題來處理,Raft也使用了分而治之的思想把算法流程分爲三個子問題:選舉(Leader election)、日誌複製(Log replication)、安全性(Safety)三個子問題;這裏先簡單介紹下Raft的流程;
  Raft開始時在集羣中選舉出Leader負責日誌複製的管理,Leader接受來自客戶端的事務請求(日誌),並將它們複製給集羣的其餘節點,而後負責通知集羣中其餘節點提交日誌,Leader負責保證其餘節點與他的日誌同步,當Leader宕掉後集羣其餘節點會發起選舉選出新的Leader;
Raft詳解
一、角色
  Raft把集羣中的節點分爲三種狀態:Leader、 Follower 、Candidate,理所固然每種狀態負責的任務也是不同的,Raft運行時提供服務的時候只存在Leader與Follower兩種狀態;
  Leader(領導者):負責日誌的同步管理,處理來自客戶端的請求,與Follower保持這heartBeat的聯繫;
  Follower(追隨者):剛啓動時全部節點爲Follower狀態,響應Leader的日誌同步請求,響應Candidate的請求,把請求到Follower的事務轉發給Leader;
  Candidate(候選者):負責選舉投票,Raft剛啓動時由一個節點從Follower轉爲Candidate發起選舉,選舉出Leader後從Candidate轉爲Leader狀態;
二、Term
  在Raft中使用了一個能夠理解爲週期(第幾屆、任期)的概念,用Term做爲一個週期,每一個Term都是一個連續遞增的編號,每一輪選舉都是一個Term週期,在一個Term中只能產生一個Leader;先簡單描述下Term的變化流程: Raft開始時全部Follower的Term爲1,其中一個Follower邏輯時鐘到期後轉換爲Candidate,Term加1這是Term爲2(任期),而後開始選舉,這時候有幾種狀況會使Term發生改變:
  1:若是當前Term爲2的任期內沒有選舉出Leader或出現異常,則Term遞增,開始新一任期選舉
  2:當這輪Term爲2的週期選舉出Leader後,事後Leader宕掉了,而後其餘Follower轉爲Candidate,Term遞增,開始新一任期選舉
  3:當Leader或Candidate發現本身的Term比別的Follower小時Leader或Candidate將轉爲Follower,Term遞增
  4:當Follower的Term比別的Term小時Follower也將更新Term保持與其餘Follower一致;
  能夠說每次Term的遞增都將發生新一輪的選舉,Raft保證一個Term只有一個Leader,在Raft正常運轉中全部的節點的Term都是一致的,若是節點不發生故障一個Term(任期)會一直保持下去,當某節點收到的請求中Term比當前Term小時則拒絕該請求;
三、選舉(Election)
  Raft的選舉由定時器來觸發,每一個節點的選舉定時器時間都是不同的,開始時狀態都爲Follower某個節點定時器觸發選舉後Term遞增,狀態由Follower轉爲Candidate,向其餘節點發起RequestVote RPC請求,這時候有三種可能的狀況發生:
  1:該RequestVote請求接收到n/2+1(過半數)個節點的投票,從Candidate轉爲Leader,向其餘節點發送heartBeat以保持Leader的正常運轉
  2:在此期間若是收到其餘節點發送過來的AppendEntries RPC請求,如該節點的Term大則當前節點轉爲Follower,不然保持Candidate拒絕該請求
  3:Election timeout發生則Term遞增,從新發起選舉
  在一個Term期間每一個節點只能投票一次,因此當有多個Candidate存在時就會出現每一個Candidate發起的選舉都存在接收到的投票數都不過半的問題,這時每一個Candidate都將Term遞增、重啓定時器並從新發起選舉,因爲每一個節點中定時器的時間都是隨機的,因此就不會屢次存在有多個Candidate同時發起投票的問題。
  有這麼幾種狀況會發起選舉,1:Raft初次啓動,不存在Leader,發起選舉;2:Leader宕機或Follower沒有接收到Leader的heartBeat,發生election timeout從而發起選舉;


四、日誌複製(Log Replication)
  日誌複製(Log Replication)主要做用是用於保證節點的一致性,這階段所作的操做也是爲了保證一致性與高可用性;當Leader選舉出來後便開始負責客戶端的請求,全部事務(更新操做)請求都必須先通過Leader處理,這些事務請求或說成命令也就是這裏說的日誌,咱們都知道要保證節點的一致性就要保證每一個節點都按順序執行相同的操做序列,日誌複製(Log Replication)就是爲了保證執行相同的操做序列所作的工做;在Raft中當接收到客戶端的日誌(事務請求)後先把該日誌追加到本地的Log中,而後經過heartbeat把該Entry同步給其餘Follower,Follower接收到日誌後記錄日誌而後向Leader發送ACK,當Leader收到大多數(n/2+1)Follower的ACK信息後將該日誌設置爲已提交併追加到本地磁盤中,通知客戶端並在下個heartbeat中Leader將通知全部的Follower將該日誌存儲在本身的本地磁盤中。
五、安全性(Safety)   安全性是用於保證每一個節點都執行相同序列的安全機制,如當某個Follower在當前Leader commit Log時變得不可用了,稍後可能該Follower又會倍選舉爲Leader,這時新Leader可能會用新的Log覆蓋先前已committed的Log,這就是致使節點執行不一樣序列;Safety就是用於保證選舉出來的Leader必定包含先前 commited Log的機制;   選舉安全性(Election Safety)   每一個Term只能選舉出一個Leader   Leader完整性(Leader Completeness)   這裏所說的完整性是指Leader日誌的完整性,當Log在Term1被Commit後,那麼之後Term二、Term3…等的Leader必須包含該Log;Raft在選舉階段就使用Term的判斷用於保證完整性:當請求投票的該Candidate的Term較大或Term相同Index更大則投票,不然拒絕該請求;
相關文章
相關標籤/搜索