raft引入no-op解决了什么问题
raft引入no-op解決了什么問題
- 1. 問題的由來
- 2. 引入no-op之后
- 3. 總結
- 4. 參考鏈接
1. 問題的由來
raft論文In Search of an Understandable Consensus Algorithm中的figure8描述了如下場景,可能會違反raft協議的一致性保證。
在這個場景中,雖然logEntry被寫入多數節點上,但是這條日志并沒有被commit。在這種情況下,寫入多數節點并沒有推進raft集群的commitIndex。
這里代表了raft的一個隱含保證:前一輪Term未Commit的LogEntry的Commit依賴于高輪Term LogEntry的才能Commit。raft這個隱含的特點,不過不認真對待,會導致違背線性一致性。因此,我們需要引入no-op。
2. 引入no-op之后
no-op是和普通的heartbeat不一樣,no-op是一個log entry,是一條需要落盤的log,只不過其只有term、index,沒有額外的value信息。
在leader剛選舉成功的時候,leader首先發送一個no-op log entry。從而保證之前term的log entry提交成功。并且通過no-op,新當選的leader可快速確認自己的CommitIndex,來保證系統迅速進入可讀狀態。(raft協議的線性一致性讀和寫也有很多講究,可以另寫一遍文章)
具體是怎么做的呢?我們看下圖:
可見,我們通過引入no-op,修復了之前可能存在的問題,提高了系統的可用性。
那么是否引入no-op之后,之前的違反一致性的情況就不會發生了呢?我們看下面的對比圖。
- 引入no-op之前,如博士論文所述,包含value信息的LogEntry有可能被覆蓋掉。
- 引入no-op之后,如果當前leader已經開始提交含有value信息的LogEntry,那么它一定將之前的LogEntry全部提交了,就算它crash了:
- 系統也會選擁有最新最全日志的candidate為leader,比如上圖,S5就不可能像之前一樣成為leader
- 就算有日志覆蓋,覆蓋的也是no-op,或者沒有復制到多數節點的LogEntry。不會是已經復制到多數節點的包含value的LogEntry。
3. 總結
通過no-op,我們解決了raft在實踐中遇到的違反consensus的問題。另外可以保證新當選的leader迅速獲取系統的CommitIndex,方便提供讀服務。
當然,引入no-op會讓系統復雜化,產生額外的落盤開銷。但是,工程上可以通過Leader Stickiness,增加pre-vote等方式避免leader頻繁切換。另外raft本身的冪等性保證也決定了,LogEntry可能會被raft系統commit多次,這些重復的log也可以被認為是no-op,可以被RSM狀態機過濾掉。
本人對raft的理解也僅限于6.824(這個不用no-op也可以過,更不要提各種工程上的優化了)、博士論文和各種文章的解讀,并沒有工程上大規模的實踐。有理解不對之處歡迎探討。
4. 參考鏈接
總結
以上是生活随笔為你收集整理的raft引入no-op解决了什么问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的链接库
- 下一篇: 什么是SPDK,以及什么场景需要它