raft協議疑問?

對於raft協議有個疑問,當客戶端請求變更時,如果因為有部分節點down機,導致沒有獲得多數選票,此時會返回失敗給客戶端嗎?

如果返回失敗給客戶端後:

1:如果某台down掉的機器恢復,原來的leader可能依然是leader,此時會將日誌複製到其他節點,導致集群告訴客戶端操作失敗,而實際上修改已經起生效?

2:如果原來的活著的機器全部停機,以前down機的機器全部恢復,此時大多數機器存活,集群重新選舉出leader正常工作,原來的leader恢復後會與新leader同步,導致更新丟失。

兩個問題:

1:情況1告訴客戶端請求失敗,實際生效,這個邏輯顯然有問題。

2:同樣的操作情況1更新生效,情況2更新失效,操作後果不可預知?

有那位大神可以回答下以上問題?


1. 不能返回失敗

2. 操作結果就是不可預知

調用者通過重試或者通過其他查詢手段獲取結果,具體到raft,就是重新更新一次或者發起一次一致性讀來確認到底有沒有寫成功。

分散式系統中的請求結果區別與單機系統,最大的特點是存在「三態」的概念。

也就是除了「成功」、「失敗」之外還有個「超時(未知)「

在單機系統中,我們調用一個函數實現一個功能,一般情況下(排除死鎖、夯死等極特殊情況)這個函數要麼成功、要麼失敗,執行的結果是確定的。

但在分散式系統中,如果某個組件(可以是一個機器,也可以是一個服務)A向另一個組件B發起 RPC(Remote procedure call)調用,組件 B 根據收到的消息內容完成某些操作,並將操作的結果通過消息返回給 A,那麼這個 RPC 執行的結果有三種狀態:「成功」、「失敗」、「超時(未知)」,稱之為分散式系統的三態。


不會有「明確的失敗」,你這種情況下,客戶端得到的結果就是unknown,如果是資料庫用raft寫redolog,那麼資料庫就要主動退出,等重啟回放日誌來得到最終一致的結論


所以情況一表明不能返回失敗給客戶端失敗嘍,實際上判斷失敗是不靠譜的事,你以為失敗其實可能成功了。情況2的問題協議的處理方式是客戶端請求得不到響應就會超時重發,隨之而來的問題是需要過濾重複請求。


1.不能返回失敗,可以返回 請求已提交,正受理之類的。

2. 如果原來的活著的機器全部停機,以前down機的機器全部恢復,此時大多數機器存活,這種情況不叫大多數。要超過一半才算大多數,所以最壞的情況也至少包含有一個之前活著的機器繼續存活。另外,raft里選leader是有限制的,並不是任意節點都可以選上的。節點收到投票請求後會和自己的日誌對比,只有哪些日誌記錄比自己大的才會投票給他。所以最終那個活著的節點會拒絕掉所有之前down機後恢復的節點的投票請求, 導致他們沒法成為leader。而只有那個活著的節點會成為新的leader。所以避免了更新丟失問題。 詳見raft原論文:5.4.1 Election restriction https://ramcloud.atlassian.net/wiki/download/attachments/6586375/raft.pdf


以下回答基於6.824實踐

1.單台機器down並不一定會導致commit失敗,只要數據複製到大多數機器仍然可以返回成功。如果失敗則客戶端重試即可。有一種情況是commit完還未給客戶端應答leader掛了。這種情況使用raft的服務要做特殊處理,比如記住客戶端請求序列號,因此不會重複變更數據。實際上客戶端首先和一個你自己的服務聯繫,這個服務本身基於raft做分散式。服務本身對以上情況做了考慮。

2.後面的leader一定會包含前面leader已經提交的log,所以不會丟數據。當然,前面有未提交數據則會丟失


推薦閱讀:

分散式一致性演算法是如何解決少數派節點的寫順序一致性問題的?
網路遊戲如何保證數據一致性?
raft協議應用方面的疑問?

TAG:分散式一致性 |