目標
Raft是一種共識算法,為了解決的問題是在分布式系統中存在的一致性問題,它是一種去中心化,強一致的算法。
概覽
為了完成上述目標,Raft的做法是將該問題分解成多個小問題:leader election, log replication,safety,membership changes;并且將節點的狀態簡化:leader, follower, candidate。
leader election(領導者選舉)
所有節點啟動時都是follower狀態;在一段時間內如果沒有收到來自leader的心跳,從follower切換到candidate,發起選舉;如果收到majority的造成票(含自己的一票)則切換到leader狀態;如果發現其他節點比自己更新,則主動切換到follower。
term
term是任期,以選舉開始為term開始。如果沒有選舉出leader就結束了,然后會發起新的選舉,并且term+1。
在單個任期內,每個節點最多只能投出一票
log replication
log replication保證了多個節點的強一致性。
復制狀態機
相同的初識狀態 + 相同的輸入 = 相同的結束狀態
這里保證的是不同的節點將以相同的確定的輸入進行更新,而不會使用不確定的值進行更新,例如當地時間等。
日志同步
在raft中,leader將客戶端請求(command)封裝到一個個log entry,將這些log entries復制(replicate)到所有follower節點,然后大家按相同順序應用(apply)log entry中的command,則狀態肯定是一致的。
當leader節點收到寫請求后會append log,并將該更新內容隨著心跳請求發送給所有follower,當收到majority個回復后會apply這個entry,并回復client成功,最后通知follower去apply 這個entry。
這里日志的提交過程有點類似兩階段提交(2PC),不過與2PC的區別在于,leader只需要大多數(majority)節點的回復即可,這樣只要超過一半節點處于工作狀態則系統就是可用的。
logs由順序編號的log entry組成 ,每個log entry除了包含command,還包含產生該log entry時的leader term。并且raft其實不是一種強一致,而是保證最終一致,leader會不斷嘗試給follower發log entries,直到所有節點的log entries都相同。
raft的log保證以下兩點:
如果不同日志中的兩個條目有著相同的索引和任期號,則它們所存儲的命令是相同的。
如果不同日志中的兩個條目有著相同的索引和任期號,則它們之前的所有條目都是完全一樣的。
leader和follower的日志狀態
從上面可以看出,一個Follower可能會丟失掉Leader上的一些條目,也有可能包含一些Leader沒有的條目,也有可能兩者都會發生。丟失的或者多出來的條目可能會持續多個任期
擁有最新的已提交的log entry的Follower才有資格成為leader
Leader只能推進commit index來提交當前term的已經復制到大多數服務器上的日志,舊term日志的提交要等到提交當前term的日志來間接提交(log index 小于 commit index的日志被間接提交)。
Election safety
raft的選舉安全性是為了保證系統中只有一個leader,從而防止了腦裂。
保證手段:1.一個節點某一任期內最多只能投一票;2.只有獲得majority投票的節點才會成為leader。