煩人的資料不一致問題到底怎麼解決?——透過“共識”達成資料一致性

huorongbj發表於2018-08-24

       本文是本系列的第二篇。是前一篇《 不知道是不是最通俗易懂的《資料一致性》剖析了 》的後續內容。


01 “共識”是什麼?為什麼會產生?

        一致性問題其實是一個「 結果 」,本質是由於資料冗餘導致的,如果沒有冗餘,也就不會有一致性問題了。

        分散式系統裡的各個子系統之間之所以能夠相互協作,就是因為其之間冗餘了相同的資料作為“信物”,要不然我都不認識你的話,為什麼要配合你幹活呢。所以這個“信物”變了,你得通知我,要不然我又不認識你了。這個“信物”變更達成一致性的過程稱作達成「 共識 」。所以:

一致性問題是結果,共識是為達到這個結果所要經過的過程,或者說一種手段。


        在分散式系統中,冗餘資料的場景不限於此,因為規模越大的系統,越不能容忍某一個子系統出問題後產生蝴蝶效應,所以往往會做高可用。小明1號倒下了還有千千萬萬個小明X號在堅守崗位,理想中的全天候24小時提供服務~。高可用的本質是透過相同資料儲存多個副本,並都可對外提供服務。比如每個小明X號都有一本《按摩指法白皮書》,誰請假了都可以由其它小明X號提供相同的按摩服務。但是這個本《按摩指法白皮書》改了,就得通知到每個人,因為這是服務的全部和來源,所以在做了高可用的叢集中資料冗餘的問題更為突出。


        實際上,如果分散式系統中各個節點都能保證瞬時響應、無故障執行,則達成共識很容易。就好像我們人一樣,在一定範圍內只要吼一嗓子,透過穩定的空氣傳播,相關人是否接收到這個訊息,並且給出響應幾乎可以是“瞬時”的。但是正如〖 上篇 ,←點我〗文中提到,這樣的系統只停留在想象中,響應請求往往存在延時,網路會發生中斷,節點發生故障,甚至存在惡意節點故意要破壞系統。這就衍生出了經典的「 拜占庭將軍問題 」[1]。


02  拜占庭將軍問題

        我們一般把「拜占庭將軍問題」分為2種情況來看待:

        ■ 拜占庭錯誤。表示透過偽造資訊進行惡意響應產生的錯誤。

        ■ 非拜占庭錯誤。沒有進行響應產生的錯誤。

        這個問題的核心在於:

如何解決某個變更在分散式網路中得到一致的執行結果,是被參與多方都承認的,同時這個資訊是被確定的,不可推翻的。

        好比如何讓所有的小明X號收到的都是《按摩指法白皮書Ⅱ》,而不是其它的,並且把原來的那本銷燬掉。這個問題衍生出了很多“共識”演算法,解決「 拜占庭錯誤 」的稱作Byzantine Fault Tolerance(BFT)類演算法,解決「 非拜占庭錯誤 」的稱作Crash Fault Tolerance(CFT)類演算法。從這個2個名字中也可以看出,本質的工作就是「 容錯 」。有的小夥伴在平時的工作中可能對「容錯」的重要性感知沒那麼強烈,不就產生一個BUG或者異常資料麼,但是在航天領域,一個小錯誤可能導致整個發射的失敗,代價非常巨大。

        對「拜占庭將軍問題」想深入的瞭解的,可以自行查閱相關資料,這裡就不展開了,文末附上提出時的論文。


        我們常見的軟體開發中一般不會考慮「拜占庭錯誤」,但它是區塊鏈專案的必需品。不過在主流的分散式資料庫中,皆能看到「非拜占庭錯誤」的身影,諸如Tidb的Paxos演算法,CockroachDB的Raft演算法。雖然我們大家在日常的coding中,對資料庫底層原理的瞭解並不是必須項。但是隻要當我們涉及到應用程式級別的高可用時,那麼至少「非拜占庭錯誤」是必須要面臨的一道坎。


03  BFT類演算法

        BFT型別演算法又有2個分支。「 基於確定性的 」和「 基於機率的 」。

        先聊聊「基於確定性的」,此類演算法表示一旦對某個結果達成共識就不可逆轉,即共識是最終結果。它的代表作是PBFT(Practical Byzantine Fault Tolerance)演算法[2],自從有了央行背書(區塊鏈數字票據交易平臺),名聲更大了。演算法的原理,如下圖:

煩人的資料不一致問題到底怎麼解決?——透過“共識”達成資料一致性

▲圖片來源於網路,版權歸原作者所有

        拿軍隊來比喻,這裡的直線C可以認為是“總司令”,直線0是“軍長”,直線1、直線2、直線3都是“師長”,值得注意的是3號師長叛變了。整個過程這樣解釋:

        ■ 「request」:總司令給軍長下了一個命令,“幹!”。

        ■ 「pre-prepare」:軍長把命令又廣播給3個師長。

        ■ 「prepare」:每個師長收到並同意之後將傳送“收到”給軍長和其他兩個師長。

        ■ 「commit」:每個師長收到2f個 師長(軍長不做prepare) 的“收到”請求後傳送“隨時開幹”給軍長和其他兩個師長。(f為可容忍的拜占庭節點數)

        ■ 「reply」:每個師長收到2f+1條“隨時開幹”訊息之後,就能認為總司令的命令在相關的師長中都到達了“隨時開幹”的狀態,那麼他就直接開炮了!

        真正深入瞭解PBFT的話還有很多內容,這裡就不繼續展開了,有興趣的小夥伴自行查閱文末論文地址或者關注公眾號後直接 後臺回覆“一致性”打包下載


        再聊聊「基於機率的」,此類演算法的共識結果則是臨時的,隨著時間推移或某種強化,共識結果被推翻的機率越來越小,成為事實上的最終結果。它的代表作是PoW(Proof of Work)演算法,曾經高達2W美元/個的比特幣就是基於這個演算法來實現的。演算法的原理拿“修仙”來做個簡單的比喻(實際位元中的演算法比這更復雜):

        ■ 自己努力修煉,並讓神仙中大於一半的人認可你的修為,同意你成仙。

        ■ 隨之你就成為了神仙。並且參與到評判後續其他人是否可以成為“神仙”的事情中去。

        ■ 這個事情如果想透過賄賂來達到的話,隨著這個團隊的人數越多,賄賂的成本越大,就可以認為去做賄賂的人越少,那麼導致被誤判的機率就越低,最終就越可信。

        被誤判的機率公式是: 0.5 ^ 個數,如果個數=6的話,誤判的機率是1.5625%。如果個數=10的話,就已經是0.09765625%了,指數級下降。


        值得注意的是,「基於確定性的」和「基於機率的」對於不合作節點的標準是不同的, 前者至多能容忍1/3,後者是小於1/2


04  CFT類演算法

        正如上面所說CFT類演算法解決的是分散式系統中存在故障,但不存在惡意節點的場景(即可能訊息丟失或重複,但無錯誤訊息)下的共識達成問題。「拜占庭將軍問題」的提出者Leslie Lamport也在他另外的論文[3]中提出過「Paxos問題」,與這相似。在論文中透過一個故事類比了這個問題,如下:

希臘島嶼Paxon 上的「 執法者 」在「 議會大廳 」中表決透過『 法律 』,並透過「 服務員 」傳遞紙條的方式交流資訊,每個「 執法者 」會將透過的『 法律 』記錄在自己的「 賬目 」上。問題在於「 執法者 」和「 服務員 」都不可靠,他們隨時會因為各種事情離開「 議會大廳 」,並隨時可能有新的「 執法者 」進入「 議會大廳 」進行法律表決。

使用何種方式能夠使得這個表決過程正常進行,且透過的『 法律 』不發生矛盾。

        —— 百度百科

        這裡的關鍵物件在我們的系統中,可以類比為:

        ■ 議會大廳 = 分散式系統

        ■ 執法者 = 某個程式

        ■ 服務員 = RPC通道

        ■ 賬目 = 資料庫

        ■ 法律 = 一次變更操作


        Leslie Lamport自己也提出瞭解決這個問題的演算法,「 Paxos 」演算法[4]。這個演算法的關鍵由以下3個定義來體現:

        ■ 每次“變更”都有個唯一的序號,並且能夠透過它識別新舊

        ■ 「執法者」只能接受比已知的“變更”更新的變更

        ■ 任意兩次“變更”必須有相同的「執法者」參與

        這3點僅僅是保證一致性的最關鍵部分,全部內容還有很多。有興趣的小夥伴自行查閱文末論文地址或者關注公眾號後直接 後臺回覆“一致性”打包下載


        「Paxos」演算法是一種無領導人(Leaderless)演算法,實現比較複雜,所以產生了很多變種來簡化它,其中名氣最大的應該是「 Raft 」,2013年才問世。「Raft」演算法是一種領導人(Leadership)的演算法。由以下2個過程保證達成共識:

        ■ 只會存在一個活著的領導人,領導人負責跟隨者的資料同步。

        ■ 如果領導人“失聯”了,那麼每個跟隨者都可成為候選人,最終比較誰的term最新,誰就是新的領導人。這個term是每個節點內部維護的一個自增數。

        雖然跟隨者的投票秉承先到先得,但是還是會遇到多個term相同的候選人獲得了相同票數(簡稱「 分割投票問題 」),那麼進行新一輪投票,直到決出勝負為止。由於Raft用隨機定時器來自增term,加上網路是不穩定的,所以再次遇到相同票數的機率就大大降低了。

        完整的過程更復雜一些,有一個Raft演算法的動畫推薦給大家,有興趣的可以瞭解一下:


        題外話,大家經常用的Zookeeper裡的「 ZAB 」(ZooKeeper Atomic Broadcast)演算法也是CFT類演算法,是以Fast Paxos演算法為基礎實現的。


05  結語

        回過頭來看,我們發現,想要更嚴謹的一致性,那麼就需要增加相互通訊確認的次數,但是這會導致效能低下,正如PBFT和Paxos一樣。但是分散式系統就是這樣,到處都需要 Balance,找到最適合的才是最重要的

        聊完了資料層面的「共識」問題,我們下回再聊聊「分散式事務」的問題,圍繞著常見的CAP、BASE理論展開。

        最後如果說想成為資料一致性專家,問有沒有捷徑的話。去閱讀老爺子Leslie Lamport的論文就是捷徑,他的個人主頁: 。


▶ 微信後臺回覆“一致性”關鍵字,可打包下載喲~

[1]《The Byzantine Generals Problem, ACM Transactions on Programming Languages and Systems》,Leslie Lamport,1982。

連結:

[2]《Practical Byzantine Fault Tolerance》,Miguel Castro&Barbara Liskov,1999。

連結:

[3]《The Part-Time Parliament》,Leslie Lamport,1998。

連結:

[4]《In Search of an Understandable Consensus Algorithm》,Diego Ongaro&John Ousterhout,2013

連結:


作者: Zachary(個人微訊號:Zachary-ZF)

微信公眾號(首發): 跨界架構師 <-- 點選查閱近期熱門文章

定期發表原創內容: 架構設計丨分散式系統丨產品丨運營丨一些深度思考

掃碼加入小圈子 ↓

煩人的資料不一致問題到底怎麼解決?——透過“共識”達成資料一致性


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31544142/viewspace-2212807/,如需轉載,請註明出處,否則將追究法律責任。

相關文章