過去這幾十年,分散式系統的「數據一致性」精華都在這了!

来源:https://www.cnblogs.com/Zachary-Fan/archive/2018/09/10/consistency3.html
-Advertisement-
Play Games

閱讀目錄 為什麼需要事務 事務的來源 分散式系統中的事務問題 分散式事務的解決方案 結語 暫時還未涉及的園友們,可以收藏防身哦~ 為什麼需要事務 事務的來源 分散式系統中的事務問題 分散式事務的解決方案 結語 暫時還未涉及的園友們,可以收藏防身哦~ 為什麼需要事務 事務的來源 分散式系統中的事務問題 ...


閱讀目錄

 

暫時還未涉及的園友們,可以收藏防身哦~

 

  本文是本系列的第三篇。與前兩篇《不知道是不是最通俗易懂的《數據一致性》剖析了》、《煩人的數據不一致到底怎麼解決?——通過“共識”達成數據一致性》形成完整的「數據一致性」合集。

  

一、為什麼需要事務

  如果說「共識」解決的是「水平」問題,那麼「事務」解決的是「垂直」問題。是如何讓一條繩上的螞蚱共同起舞?

 

  事務只是一個電腦術語,而事務的體現形式其實在我們生活中也無處不在。任何我們認為應該是這樣的事情,去確保它達到預期的過程就是「事務」。 往小了說,我們平時在走路的時候,向前擺動左手的同時抬右腿,如果不是這樣的話就是不一致,別人會說你走路不協調。所以我們小時候父母會通過各種方式教會我們這個,這些各式各樣的方式就好比我們在軟體開發中去實施「事務」一樣,一題是多解的。

 

  

二、事務的來源

  提到事務不得不提到「XA規範」[1],這是分散式還沒大行其道的時期,被大多數的資料庫作為其內部分散式事務實現的介面標準。

▲圖片來源於論文中,版權歸原作者所有

 

  「XA規範」就是上圖中「RM」和「TM」的交互規範和介面定義。僅僅是定義了xa_和ax_系列的函數原型以及功能描述、約束和實施規範等,並不包括建議的實現方式。後面會提到的兩階段提交(2PC)是「TM」協調「RM」們完成事務的方法。

 

  所以其實可以說,事務起源於資料庫,輝煌於分散式系統。在摩爾定律還適用的時候,軟體系統為了承載更大的流量或者說用戶數,開始運用「分治」的思想來設計。然後隨著互聯網的蓬勃發展,B/S應用大行其道的背景下,分散式系統越來越常見。並且隨著一個個巨無霸互聯網公司的出現,越來越被鼓吹和傳頌。

一輪明月的背後是一個陰暗面,從來不讓人看見。

  能被吹捧的永遠是有益的一面,再加上耀眼的數據:多少TPS、多少QPS,更抓人眼球。但是這背後為了讓「分治」後的系統能夠儘可能的像單個個體一樣運作,各類專家學者們通過多年研究,才有瞭如今的各種著名理論和解決方案。

 

 

三、分散式系統中的事務問題

  正如前面所說,事務問題其實一直存在,只是在分散式系統中被放大了。並且隨著系統拆分的粒度越細,問題的複雜度成指數上升。

 

  分散式系統的事務,不得不提到被廣為流傳的兩個理論:「CAP」、「BASE」。

 

  「CAP」理論由Eric Brewer在2000年PODC會議上提出[2],所以還被稱為Brewer定理。是Eric Brewer在Inktomi期間研發搜索引擎、分散式web緩存時得出的一個猜想:

It is impossible for a web service to provide the three following guarantees : Consistency, Availability and Partition-tolerance.

  後來Seth Gilbert和Nancy Lynch對其進行了證明[3],成為我們熟知的「CAP」定理(感謝園友@bangerlee的信息收集)。

 

  對,就是下麵這張經典的圖。

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

 

  • 一致性(consistency):這裡的一致性指是「線性一致性」。(關於線性一致性的解釋,點我可閱讀

  • 可用性(availability):每個請求都在一定時限內得到響應。

  • 分區容忍性(partition-tolerance):這應該是這三點中最晦澀的。允許丟失以一個節點發給另一個節點的任意多的消息。只要是分散式系統,這項是無法逃避的,因為網路、硬體說不准啥時候就出問題了。

  舉個不是特別嚴謹的例子,這就好比要實現一個系統不能產生BUG(C),並且10天內完成上線(A),以及需要多人團隊一起協作進行(P)。我們做開發的也很清楚這三者是無法兼得的。況且只要是一個組織,團隊協作是無法避免的,正如這裡的分區容忍性一樣,比如得考慮人員請假的問題。剩下的2項,如果說可以達到沒有BUG的話,那就是時間無限延長,但也只是無限趨近於0,並不能達到真正的0,因為沒有人可以保證發現了所有的BUG。

 

  「BASE」理論是由時任ebay架構師的Dan Pritchett提出的[4],本質上就是對「線性一致性」的弱化。弱化的方式正如本集合的第一篇文章中所提到的「順序一致性」和「最終一致性」。(關於這兩種一致性的解釋,點我可閱讀

  「BASE」理論解釋如下:

  • 基本可用(Basically Available)。分散式系統在出現故障時,允許損失部分可用功能,保證核心功能可用。

  • 軟狀態(Soft State)。狀態可以有一段時間不同步,且這個狀態不影響系統可用性。

  • 最終一致(Eventually Consistent)。確保最終數據能夠一致,而不是時時保持強一致。

  「BASE」理論的提出並不是取代「CAP」理論,讓我們在實際的工作中就可以完全的撇開「線性一致性」。並不是這樣,而是引導我們可以區分核心和非核心,然後分別對待,核心部分還是需要用CAP理論來保證「線性一致性」。為什麼要區別對待?根本上還是無法容忍「線性一致性」帶來的巨大的性能損耗,因為它是反可伸縮性的。但是只要涉及到Money之類的高敏感數據的操作部分,還是必須保證「線性一致性」。

  還是上面的例子,我們側重於降低核心功能的BUG,不花過多精力在非核心功能上(BA)。我們允許產生不影響核心功能的BUG(S),但是必須最終要修複(E)。

 

 

四、分散式事務的解決方案

  如果說「CAP」理論和「BASE」理論是「道」,那麼圍繞這兩個理論演化的解決方案就是「術」。對我們來說,在實際的運用中根據所處的場景找到最合適的,是我們最重要的事。

 

  以「CAP」為基礎的強一致性解決方案都會引入一個類似“協調器”的東西來作為全局事務的掌控者,可以來看一下。

 

01 兩階段提交(2PC)[5]

 

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

 

  印象中左耳朵耗子(陳皓)之前拿西方結婚時的儀式做過一個形象的比喻。大致好像是牧師分別詢問男女雙方“你願意嗎?”相當於這裡的「請求提交」,得到的“yes”相當於「是」這個答覆。然後再要求給對方帶上戒指,這個要求就相當於這裡的「提交」,帶完戒指之後的反饋就是「ACK」。

  另外值得註意的是,參與者在答覆「是」之前會將自己的內部資源變為阻塞狀態。因此如果在產生阻塞後協調者出問題,那麼這些被阻塞的資源有可能就一直不被釋放了,需要額外的介入。

  2PC相對來說是最簡單的事務模型,但缺點也更多。其它缺點諸如:在某些場景下的數據不一致(參與者與協調者共同與「提交」環節掛了)、阻塞範圍過大等問題。

 

02 三階段提交(3PC)[6]

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

 

  3PC的出現就是通過增加複雜度(性能也因此降低)來解決或優化2PC中的一部分問題。本質的變化就是在2PC的「請求提交」之後增加了一個「準備提交」環節,以增加每個參與者需要等待其它的參與者確認後方可進行具體的操作。

  • 「阻塞」這個動作延後到這個「準備提交」環節再做,使得阻塞範圍縮小為2PC的2/3(圖中背景黃色和綠色部分)。正如上面的例子,在交換戒指之前增加了把戒指交給牧師的動作。

  • 同時還解決了協調者的單點問題。故障恢復或者新接替的協調者,可以利用「準備提交」產生的狀態結果,來作為參與者和協調者在「提交」出現故障恢復後的界定依據。還是前面的例子,誇張點,交換戒指的時候我失憶了,意識恢復後我只要看到牧師手掌上托著戒指或者我的手上已經被戴好了戒指,就知道我的妻子已經答應了,我只要繼續給她做帶戒指這個事就好了。

  • 新引入了timeout機制,在發生超時執行預設約定,避免了永久阻塞,也因此對多個參與者下的100%數據一致性作出了妥協。比如,協調者在向參與者A發送「doCommit」時timeout了,會引發廣播「abort」,但是這個「abort」又未能投遞到參與者B,導致參與者B執行了「ACK」後的timeout預設約定「commit」。

 

03 TCC

  在國內,由於阿裡的光環加持下TCC好像更火,風頭蓋過了2PC和3PC。其本質上是另闢蹊徑達到了和3PC類似的效果。

 

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

 

  • 通過運用本地事務代替了全局事務,使得可以不需要協調者的存在,避免了協調者的單點問題

  • 3PC中協調者的另一個作用:故障恢復後的數據一致性。在TTC里通過事務日誌來確保

  這個概念最初是由Pat Helland於2007年提出的[7],那時還叫「Tentative-Confirmation-Cancellation」,在2008年的軟體開發2.0技術大會上支付寶CTO(程立)將其在國內推廣開來。

 

  以上這三種就是主流的DTS(Distributed Transaction Service)框架。值得一提的是,不管是3PC還是TCC,只要涉及到故障恢復或者重試機制,那麼「冪等性」問題必須要提上來了。比如3PC中「提交」階段某個參與者和協調者同時掛了,但是這個參與者在掛之前已經做了commit操作。那麼故障恢復後其實沒人知道它是否執行過了commit,協調者只會為了能100%確保commit指令被送達,又會發起一次commit通知,這時候如果沒有做好「冪等性」就會發生重覆commit的問題。

 

 

  下麵聊聊以「BASE」理論為基礎的解決方案。

 

01 非同步消息——本地消息表


▲點擊圖片可查看大圖

 

  這種實現方式的思路,源於ebay,與提出BASE理論在同一篇論文中[4]。設計思想是將遠程分散式事務拆分成一系列的本地事務,藉助關係型資料庫中的表即可實現。

 

02 非同步消息——不支持事務的MQ


​▲點擊圖片可查看大圖

 

  其實大部分的MQ都是不支持事務的,所以我們需要自己想辦法解決可能出現的MQ消息未能成功投遞出去的問題。有個便宜可以撿的是,如果需投遞的MQ消息條數僅有1的話,可以將本地事務的commit放於消息投遞之後即可避免此問題。偽代碼如下:

try{ 
    beginTrans(); 
    modifyLocalData1(); 
    modifyLocalData2(); 
    deliverMessageToMQ(); 
    commitTrans(); 
}
catch(Exception ex){ 
    rollbackTrans(); 
}

 

03 非同步消息——支持事務的MQ

 


​▲點擊圖片可查看大圖

 

  據我所知,目前唯一支持事務的MQ框架是RockerMQ,並且於近期才開源了事務部分實現,《RocketMQ 4.3正式發佈,支持分散式事務》(http://www.infoq.com/cn/news/2018/08/rocketmq-4.3-release)。這樣的確能省很多事~,直接放一張阿裡方面給出的圖感受一下實現細節。

 


▲圖片來源於網路,版權歸原作者所有(點擊圖片可查看大圖)

 

  不過其實有一個疑點我沒有去驗證,有知道的小伙伴們可以留言下,就是RocketMQ是否有防止consumer(上圖中的訂閱方)在消費完成後發送的ACK丟失的機制。如果能達到這點,對於consumer內部的方法冪等性需求就低了很多。

 

04 Saga


​▲點擊圖片可查看大圖

 

  Saga是1987年就提出的概念[8],核心是:

  • 將一個分散式事務拆分為多個本地事務,並且擊鼓傳花給下一個,不用阻塞本地事務等待響應。且允許嵌套至多一層子事務。

  • 除了最後一個參與者之外,都需要定義一個「回滾」介面,便於在遇到無法進行下去的情況下撤銷之前上游系統的修改。當然這裡的撤銷除了Update還可以是沖抵類的操作。

  Saga原則上是個鏈式的「長活事務」,整個處理耗時可能會很長。所以可以通過增加save point(保存點,類似於游戲里的存檔),便於故障恢復和提速,如向前恢復(重試)和向後恢復(回滾)。不過,也可以並行多個子事務,但一般在運用中心節點的Saga模式中,如圖。


​▲點擊圖片可查看大圖

  只是在我們打破了鏈式規則後必須要額外確保執行了「回滾」之後再接收到「正向請求」,等於“請求無效”的效果。中心節點模式還有一個比較大的好處是能夠更好的避免事務之間的迴圈依賴關係。

 

05 Gossip協議

  額外提一下,這個其實是一個具體的、運用BASE理論實現的協議,藉由Cassandra的熱火而讓更多人知道了。這協議一般會用於數據複製、P2P拓撲構造、故障探測等。

 

 

  看這些案例我們可以發現,基於「CAP」的解決方案都是線上的,而「Base」是允許離線的。好比前者是,累倒了必須得馬上爬起來繼續乾貨,要不然就是失敗。而後者是,慢慢來,只要最終能幹完。

  不管怎樣,如果每個解決方案中增加「重試」和「回滾」會大大提升程式的自我修正能力,以降低需要人為介入的比例。識別是否需要人為介入的方式就是類似於「對賬」的機制,這個機制就是兜底的。最後還需要做一道選擇題來防止混亂:確保參與者的介面符合「冪等性」,或者在中間件里做到「正好一次(Exactly-once)」。

  這些基於「BASE」的解決方案都是可以作為「CAP」解決方案出現問題時的PlanB來用的,起到補充作用。當然,如非必要,可以優先考慮基於「BASE」的方案,畢竟這才是天然易伸縮的,自然也能帶來更好的性能。

 

 

五、結語

  解決方案如此多,所以不管我們是架構師、還是在成為架構師的路上,甚至在日常生活中,都需要養成Balance的習慣,找到那個最適合的方案。

  最後還有一招終極大法 —— 減少冗餘。

是亦彼也,彼亦是也,彼亦一是非,此亦一是非。 ——莊子

  「事物都具有兩面性」,所以,在選擇走向分散式之前,慎重考慮下是否有必要,以免給自己徒增麻煩。

 

 

  論文可在微信公眾號後臺直接回覆關鍵字“一致性”,打包下載。下篇將開啟「高可用」主題,敬請期待~

 

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

[1] Distributed TP: The XA Specification , X/Open Company Ltd. , 1991

鏈接:https://publications.opengroup.org/c193

[2] Harvest, Yield, and Scalable Tolerant Systems, Armando Fox , Eric Brewer, 1999

鏈接:https://cs.uwaterloo.ca/~brecht/servers/readings-new2/harvest-yield.pdf

[3] Brewer’s Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web, Seth Gilbert, Nancy Lynch, 2002

鏈接:https://pdfs.semanticscholar.org/24ce/ce61e2128780072bc58f90b8ba47f624bc27.pdf

[4] Base: An Acid Alternative, Dan Pritchett, 2008

鏈接:http://delivery.acm.org/10.1145/1400000/1394128/p48-pritchett.pdf

[5] Consensus Protocols: Two-Phase Commit, Henry Robinson, 2008

鏈接:http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/

[6] Consensus Protocols: Three-phase Commit, Henry Robinson, 2008

鏈接:http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/

[7] Life beyond Distributed Transactions:an Apostate’s Opinion, 2007

鏈接:https://cs.brown.edu/courses/cs227/archives/2012/papers/weaker/cidr07p15.pdf

[8] Sagas, Hector Garcaa-Molrna  & Kenneth Salem, 1987

鏈接:https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf

 

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

微信公眾號(首發):跨界架構師<-- 點擊後閱讀熱門文章,或右側掃碼關註 -->

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • /* * pending:初始化成功 * fulfilled:成功 * rejected:失敗 * */ function Promise(executor) {// 執行器 this.status = 'pending'; this.value = undefined; this.reason =... ...
  • 序言: 剛結束公司的三個月試用期,意味著我即將正式步入社會成為廣大從事IT行業的一員。作為一個編程小白,無論從技術層面還是知識層面都是比較薄弱的,想要成為一個優秀的程式員不斷的學習與探索是不可避免的。我相信一切的付出與收穫是成正比的!Fighting! 這幾天在做公司的實際項目的時候,需要實現選中B ...
  • 前端火熱的框架層出不窮,作為碼農的我們,依舊需要去學習,去探索新的問題,學習新技術,其實就是為了寫一手好的,自認為是高質量的代碼。今天主要分享一下前端最火的框架vue,也是我比較喜歡的框架。 vue上手可以說是比較輕鬆而且簡單,如果你用過angular,react,你也會很喜歡vue。vue的核心思 ...
  • css實現單行文本溢出顯示 ... 直接上效果:相對於多行文本溢出做處理, 單行要簡單多,且更容易理解。 實現多行文本溢出顯示... 方法: 因使用了WebKit的CSS擴展屬性,該方法適用於WebKit瀏覽器及移動端; -webkit-line-clamp用來限制在一個塊元素顯示的文本的行數。 為 ...
  • 使用Canvas路徑畫圖需要註意方向,畫圖方向是順時針還是逆時針需要記住。下麵讓我們看看Canvas常見路徑方向。 arc 參數值 參數 | 描述 | x | 圓的中心的 x 坐標。 y | 圓的中心的 y 坐標。 r | 圓的半徑。 sAngle | 起始角,以弧度計。(弧的圓形的三點鐘位置是 0 ...
  • 引用: JavaScript Cookie - by runoob.com Cookie是儲存在電腦文本文件中的數據,用於保存訪問者的信息,並可以在下次打開頁面時引用。 頁面在設置/引用訪問者信息時,需要在JavaScript中對Cookie進行設置,獲取和檢索三個函數。 例如當訪問者首次訪問網頁時 ...
  • nodejs 簡單的封裝一些mysql模塊 實現一個方法根據不同傳參進行增刪改查 首先要 npm install mysql 代碼如下 傳入參數如下 objHost 資料庫的基本信息如下 sql 就是sql語句 添加 修改 刪除 查找 callback回調 操作完成後拿到數據的回調 add 在添加時 ...
  • JavaScript有兩種數據類型,基礎數據類型和引用數據類型。基礎數據類型都是按值訪問的,我們可以直接操作保存在變數中的實際的值。而引用類型如Array,我們不能直接操作對象的堆記憶體空間。引用類型的值都是按引用訪問的,即保存在變數對象中的一個地址,該地址與堆記憶體的實際值相關聯。 一、深拷貝和淺拷貝 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...