分散式一致性演算法是如何解決少數派節點的寫順序一致性問題的?

設系統有3個節點, A(Leader節點), B(Follower節點), C(Follower節點); 對系統分別做W1, W2這2次針對變數a的寫操作; 先做W1的時候, 節點A,B作為大多數提交了commit, 實現了W1的成功寫操作, 而C節點沒有來得及commit, 也沒有來得及從A節點同步; 這時進行了W2寫操作, 那麼C節點還會參與commit過程么??????如果不參與, 那麼只剩了A, B 2個節點, 無法判斷大多數; 如果參與, 那麼C節點相當於W2發生在W1之後了!


這個問題本身解決起來並不複雜:每個事務及其日誌可以有順序號,C收到W2的時候,是可以知道還有之前的事務沒有收到,它可以等收到W1後再操作。Raft就要求這種順序性,不過這種做法可能帶來性能的瓶頸和抖動。OceanBase的一致性協議為什麼選擇 paxos而不是raft?


首先一點,基本上的強一致性協議都會確保 w1的日誌在 w2之前,確保兩者的順序關係。具體來說

1.你可以 commit w2但是不 apply, paxos 的實現就可以這樣。但是 apply 的時候順序 apply 已 commit 的日誌

2 順序 commit ,w2隻有等 w1commit 了了才會commit,比如 ZAB,raft

還有一點貌似更像是針對題主的疑惑,類 paxos強一致性協議 的底層是 日誌,保證了不同節點相同位置 commit 的日誌必然相同。日誌是尾部追加,w2的日誌同步到從節點,是要寫入到和主節點相同的位置,意味著主節點 w1日誌在w2之前,從節點必然也如此。而日誌是追寫的,因此實際上落盤時不會存在 w2寫入,而 w1沒寫入。在發送端排隊有序發送和在接受端排隊再寫入都可以。


https://github.com/baidu/bfs/blob/master/src/nameserver/raft_node.cc#L495

https://github.com/baidu/bfs/blob/master/src/nameserver/nameserver_impl.cc#L72

直接看某種業務應用系統源碼,可能讓概念更清晰,真正的摸的著的那種實在感。

百度的bfs 項目對於理解Raft以及它的用途(如何結合業務系統)挺有幫助。


研究過paxos類協議時確實會碰到,我之前了解了paxos後寫過總結,不是專門解釋這個,是個人覺得不太好理解的地方記錄 https://zhuanlan.zhihu.com/p/23811020


  • 首先這個問題來自題主一個錯誤認識

如果不參與, 那麼只剩了A, B 2個節點, 無法判斷大多數

一致性協議中的大多數是相對整個cluster而言的,即使C出問題了,或者是變成了掉隊者 (straggler),只要它沒有從全局config中刪去,這個集群仍然是3個總數節點。這樣,由於滿足majority的條件,(A, B 正常) W2 是完全可以正常commit的。

明白了這個,問題就不存在了。C 出了問題,是不影響 W2 的commit的。

  • 再隨便說下作為straggler,C 的sync問題

在Raft 協議里,我們保證

  1. 所有的op都經過leader (這個很trivial)
  2. 不管什麼情況下選出來的leader都有最完整的正確順序的op log,這裡的op包含了commit的,也包含非commit的。 (non-trivial 需要看下Raft 論文)

這樣sync就會變得很簡單。 leader 節點直接把自己的log 壓縮後發給 straggler 就可以了。


1. 只有ab兩個節點寫入成功了,這兩個節點不就是三個中的大多數成功了嗎。

2. 根據raft協議,w2在w1寫入成功之前,是不會成功的。

題主去把raft看一遍,這些問題都有答案。


一般實際系統中,C收到W2後,會因為日誌不連續而主動拉取W1或者等待W1的日誌到來後,才給A響應。

若在響應主機時(一般備機在日誌落盤後即可響應,此時還未replay)不考慮日誌是否連續,那replay時,也是必須按序的。


簡單來說 一致性協議只會保證兩個同時發生的寫操作在每台機器上執行的順序是一致的 而不會保證它們之間的先後順序

兩個寫操作 可以看作是對paxos 日誌上同一個位置的搶佔操作 必然只會有一個成功 另外一個操作則會返回失敗而在前端進行重試


推薦閱讀:

網路遊戲如何保證數據一致性?
raft協議應用方面的疑問?

TAG:分散式系統 | 分散式一致性 |