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:分散式一致性 |