1 特殊場景-投票環節follower的贊成和拒絕
在叢集的每一次重新選舉過程中,總會有一個節點首先成為candidate,然後向其他節點發起投票請求。這時由于各種情況,follower節點需要根據自身的目前狀态選擇是投贊成票還是拒絕票.vote_記錄的是給誰投了贊成票
case1 小紅(id=1,term=1)作為follower還沒有給任何人投票(vote_=0)
- 小紅收到了小藍(id=3)MsgVote,此時會立即給小藍回複MsgVoteResp,并且更新自己的vote_為3
case2 小紅(id=1,term=1)作為follower已經投了自己贊成票(vote_=1)
- 這時候除了小紅給自己發送MsgVote,小紅會傳回贊成票,其他人給小紅投票都會傳回拒絕票
case3 小紅(id=1,term=1)作為follower給小黃(id=2)投了一個贊成票(vote_=2)
- 這時候除了小黃給小紅發送MsgVote,小紅會傳回贊成票,其他人給小紅投票都會傳回拒絕票
case4 小紅(id=1,term=1)作為follower收到了某人的term=2的MsgVote
- 上面case1到case3,假設的是投給小紅的MsgVote的term都不大于小紅自身的term
- 如果小紅收到的MsgVote的term大于自身term,小紅也會傳回贊成票,同時更新自己的vote_為發送MegVote的人
2 特殊場景-candidate被“截胡”
當小紅(id=1,term=1)成為candidate後,她發送了MsgVote給其他成員等待回複,但在這時候,小紅收到了小藍(id=3)的MsgApp(要求同步日志的請求),這時候小紅的反應:
- 如果小藍的MsgApp中的term大于等于1,小紅會自動轉為follower角色。把小藍作為leader
- 如果小藍的MsgApp的term小于1,小紅會忽略這個請求,繼續等待其他成員的回複
3 特殊場景-leader的送出日志
case1 外部用戶端正常發起一個MsgProp
- 在《白話-raft協定(一)》中,小紅争取到leader角色後,會發送MsgApp向小藍和小黃同步日志,同步成功後,小紅的本地日志如下:

- 這時用戶端發送一個新的請求MsgProp(内容為“some data”),小紅收到請求後,先把請求放在本地,不送出
- 然後小紅給其他同學(小紅小藍)發送同步消息MsgApp(index=1,logterm=1,commit=1),這裡小紅有個變量prs_[1].match = 2,記錄目前小紅的日志index
- 假設小紅先收到小黃的回複MsgAppResp(index=2),小紅會更新prs_[2].match = 2,這時小紅會發現三個人中已有兩人記錄了日志index(2),會把自己的日志狀态commit_設定為2,然後給小黃和小藍發送MsgApp資訊(index=2,logterm=1,commit=2)
- 随後小紅收到了小藍的回複MsgAppResp(index=2),小紅會更新prs_[3].match = 2,這時,叢集大部分人(本例中是全部)日志index都等于2,小紅自己的commit_也是2,小紅不再繼續發送請求
4 特殊場景-同步日志
在etcd中的raft實作中,日志的存儲分為兩部分,一部分是storage(真正持久化的資料),一部分是unstable(記憶體中的資料)
- 虛線左邊的資料是持久化的資料
- 測試用例中,小紅在成為candidate前被手動設定了term為2
- 當變為candidate時,term會自動加1,是以在unstable部分都變成了3
- 當變為leader時,會自己追加一個空的entry
5 特殊場景-作為follower被同步日志
這裡假設小紅變為了follower,接收到了小黃(leader)的同步日志請求MsgApp
- 如果小黃發送的msg中,日志索引(index)小于小紅本身已送出的索引(committed),說明小紅有一部分小黃不曾擁有的日志,這時的處理方式是小紅直接傳回MsgAppResp,把自己的送出索引(committed)告訴小黃。如果小黃發送的msg,日志索引不小于小紅本身已送出的索引,那麼會繼續下面的檢查
- 先檢查小黃msg的index,在小紅日志中所屬的term(任期),然後跟小黃msg中的logterm比較,不相等小紅會拒絕小黃的同步日志的請求。相等繼續下面的檢查
- 沖突檢查,檢查小黃msg中帶的entries中,每一個entry裡的index和term和小紅本身的日志是否相同。如果都相同,傳回0,如果有不想等的,傳回第一個不相等的index
- 小紅根據傳回的沖突的index,來判斷更新自己的哪部分日志
6 特殊場景-作為folloer被同步日志,發現日志不一緻
- 小紅(follower)的日志中已經有index為1和2的日志了,小黃(leader)發給小紅的Entry為(index1,term3),小紅在對比時候發現,index1的term在自己日志中term是1,在小黃中,term是3,兩者不一樣,發生沖突。
- 發生沖突時候,最後的日志更新以leader為主,即小紅更新自己的offset為1,用小黃的Entries替換自己的unstable部分