上篇文章淺析了raft協議(raft協議淺析),文章中有一處描述錯誤和理解不透徹的地方,在這裡再補充下。

raft論文截圖 1

第一、日誌複製流程那一段提到的日誌複製流程中的兩階段提交。是錯誤的,這裡沒有使用兩階段提交。客戶端請求打到leader節點後,leader本地寫日誌,並將日誌複製到集羣其他follower節點,如果收到大多數(超過集羣總數一半)的節點複製成功,並且滿足安全性檢查條件(存在當前選舉term的日誌複製),leader節點就認為可以提交,將log entry作用到本地狀態機,並返回客戶端寫入成功的操作,至此客戶端寫入操作完成。不存在通知follower節點該log entry已提交的過程。

其實同步commitid是沒有必要的,leader節點收到大多數節點返回的複製成功響應後就可以安全提交該log entry了,即使leader崩潰,該log entry在新的leader節點也是可見的。commitid在節點上是以volatile方式存儲的,掉電或者重啟後commitid會丟失,但是可以根據各節點已落盤的日誌恢復出來。具體怎麼恢復可以參考上述截圖。

第二、安全性問題除了選舉規則增加了選舉最新的leader,還有一條是提交規則的修改。如果提交的日誌記錄是前一任期的,則必須跟隨本屆任期的日誌記錄一起提交纔算安全提交。解釋下:

raft論文截圖2

(1)a時間段S1節點當選為term-2 leader,複製index-2日誌到S2節點,崩潰了;

(2)b時間段S5當選為term-3 leader節點,選票來自S3 S4,並接收了一條來自客戶端的請求,隨即崩潰;

(3)c時間段S1節點恢復,當選為term-4 leader,選票來自S2 S3 S4,並將index-2 日誌複製到S3節點,此時leader節點通過本地維護的matchIndex[]={2,2,2,1,1}數組發現index-2已經在大多數節點完成複製了,但是能將index-2的Log Entry提交到狀態機嗎? 不可以,原因:

(4)d時間段,如果此時S1崩潰,集羣發起term-5的選舉,S5輕而易舉可以獲勝,因為S5節點最新log Entry為(term-3,index-2),該日誌比S2和S3的(term-2,index-2)日誌新;此處日誌是節點當前最新的日誌,不是提交日誌,日誌比較優先比較term,term相等再比較index;

(5)S5當選為leader節點,會將(term-3,index-2)日誌複製到其他節點,覆蓋(term-2,index-2)

所以c時間段(term-2,index-2)log entry不能提交,什麼時候能夠提交呢?當(term-4,index-3)log entry提交時,(term-2,index-2)就可以安全提交,因為此時S5節點不可能再被選舉為leader節點。

結論:當提交的log entry的term號為前一任期號時,必須跟隨本屆任期的log entry一起提交纔算安全提交。

推薦閱讀:

相關文章