標籤:

Raft phd 論文中的pipeline 優化

Raft phd 論文中的pipeline 優化

來自專欄 基礎架構

raft phd 論文裡面是如何做 Pipeline 優化的?

貌似這裡Pipeline 的做法也是不會讓日誌產生洞, 日誌仍然是有序的

leader 和follower 在AppendEntry 的時候, 不需要等待follower 的ack 以後, 立刻發送下一個log

entry 的內容. 但是在follower 收到這個AppendEntries 的內容以後, 因為AppendEntries

會默認進行consistency check(這裡AppendEntries consistency check

指的是在執行AppendEntries 的時候, 會把之前的一個log 的index, term 也都帶上, follower

在收到這條消息以後, 會檢查這裡的index, term 信息是否與自己本地的最後一個log entry的index, term 一致,

不一致的話就返回錯誤) 那麼即使是pipeline 執行AppendEntries, 仍然會保證如果這個follower 接受後面一個entry

的時候, 必定把之前pipeline 的entry 接受了才行, 不然是不會滿足這個 AppendEntries 的約束的,

也就是說即使使用pipeline 依然可以保證Log 是不需要帶洞的. 當然raft 作者這裡的做法依然是保證簡單,

所以讓沒有通過AppendEntries concsistency check 之後, 默認就讓這個AppendEntries 錯誤,

然後讓他重試. 當然也可以有其他的處理方法

同時這裡也強調, 使用 pipeline 的話, 必須至少一個leader 與一個follower 建立多個連接?

如果一個leader 與一個follower 共用一個連接使用pipeline 的話, 那麼效果會是怎樣的呢?

其實這樣的pipeline 適合batch 是沒有多大區別的, pipeline 最大的目的應該是在latency 比較高的情況下,

也可以充分的利用帶寬, 但是如果共用一個連接的話, 在tcp 層面其實就已經是串列的, 因為tcp 同樣需要對端的ack,

才會發送下一段的報文, 雖然tcp 有滑動窗口來運行批量發送, 然後在對端重組保證有序, 其實這個滑動窗口就和batch 的作用類似.

因此如果使用單挑連接, 其實是和batch 的效果是差不多的, 使用單條連接的pipeline 其實也不會出現包亂序, 因為tcp

層面就保證了先發送的包一定是在前面的.

說道這裡其實raft 同步log和tcp 做的事情類似, 也是希望可靠有序的進行數據同步, 又希望儘可能的利用帶寬.

那麼使用多條連接的話可能存在什麼問題?

如果是一個leader 和 follower 建立多個連接的話, 即使因為在多個tcp 連接中不能保證有序,

但是大部分情況還是先發送的先到達, 即使後發送的先到達了, 由於有AppendEntries consistency check 的存在,

後發送的自然會失敗, 失敗後重試即可. 其實這裡完全也可以像tcp 那樣, 有類似滑動窗口的概念, 也就是說AppendEntries

的時候, 如果發現之前的內容還沒到達, 那麼完全可以在本地的內存中保留一份buffer, 那麼可以利用這個buffer 就不需要進行重傳了,

當然簡單的辦法仍然是重傳.

當然這裡如果引入了類似滑動窗口的概念, 在follower 端保留一份數據的話, 那麼自然也就需要擁塞阻塞演算法的存在了,

也就是說如果一個follower 節點在前面某一個連接缺少了某一個log 以後, 其他的連接一直發送數據, 這個時候該如何處理,

也就是follower 需要告知leader, 讓這個leader 不要再發送內容了, 那麼其實就和tcp 裡面的擁塞阻塞是一樣了.


推薦閱讀:

Braft的日誌存儲引擎實現分析
我對Raft的理解 - Two
Raft協議
Indexed Shared Log

TAG:Raft | 一致性 |