etcd raft選舉機制
etcd 是一個分布式的k/V存儲系統。核心使用了RAFT分布式一致性協議。一致性這個概念,它是指多個服務器在狀態達成一致,但是在一個分布式系統中,因為各種意外可能,有的服務器可能會崩潰或變得不可靠,它就不能和其他服務器達成一致狀態。這樣就需要一種Consensus協議,一致性協議是為了確保容錯性,也就是即使系統中有一兩個服務器當機,也不會影響其處理過程。
為了以容錯方式達成一致,我們不可能要求所有服務器100%都達成一致狀態,只要超過半數的大多數服務器達成一致就可以了,假設有N台服務器,N/2 +1 就超過半數,代表大多數了。
raft協議核心要點:
-
Leader選舉(Leader Election)
-
日志同步 (Log Replication)
- leader收到client的更新請求后,會講更新的內容同步給所有follower。
-
集群狀態的正確性 (Safety)
- 保證日志的一致性
- 保證選舉的正確性
服務器狀態:
-
leader
處理所有客戶端交互,日志復制等,一個任期只有一個。 -
follower
完全被動的選民,是只讀的。 -
candidate
候選人,可以被選舉為新領導。
狀態之間的轉換:
任期(terms)
如上圖,藍色代表 Election 模式,綠色代表 Operation 模式
- 在每個任期內最多一個leader
- 有些可能沒有leader
- 每一個服務會維護當前的任期值
- 每一個rpc請求中都會攜帶term值
- 如果一個peer實例擁有老的term值,則更新為最新的term值並狀態變為follower
- 一旦一個服務選舉為leader,就會進入 operation 模式
Leader選舉
etcd服務啟動后,會進入 follower 狀態,leader 心跳超時后會進入選舉狀態。
選舉總體流程圖如下:
選舉流程分解
-
初始狀態都是Follower
-
S1 超時, 變為Candidate,開始選舉, 發起投票請求
-
S1 變為Leader
-
S2 和 S3 同意投票給S1
-
-
Leader S1開始接受客戶端寫請求
- Leader接受到客戶端寫請求后,會將數據更新寫入到log中
- 如果S2和S3收到客戶端寫請求,會將請求轉發到Leader S1
- Leader會異步的將更新的log同步到Follower S2和S3
-
超過多數的Follower將數據成功同步到log后,Leader會將該條數據更新為Committed狀態,Committed index會隨着增長。
選舉的正確性
- 在每一任期內,最多允許一個服務被選舉為leader
- 在一個任期內,一個服務只能投一票
- 只有獲得大多數投票才能作為leader
- 如果有多個candidate,最終一定會有一個被選舉為leader
- 如果多個candidate同時發起了選舉,導致都沒有獲得大多數選票時,每一個candidate會隨機等待一段時間后重新發起新一輪投票(一般是隨機等待150-300ms)
日志的一致性
- 客戶端寫入數據到 leader:
- leader 將數據寫入到 log
- leader將更新的數據廣播到所有的followers
- 多數follower成功寫入log后,leader會將該數據提交到狀態機
- leader 把數據提交后,返回給client結果
- 在下一個心跳中,leader 通知follower更新已經提交的數據
- Crashed/slow followers ?
- leader會一直重試同步數據到follower,直到成功
