1. 程式人生 > >分散式系統事務一致性

分散式系統事務一致性

一 分散式系統特點

現今網際網路界,分散式系統和微服務架構盛行。業界著名的CAP理論也告訴我們,在設計和實現一個分散式系統時,需要將資料一致性、系統可用性和分割槽容忍性放在一起考慮。

1、CAP理論

在分散式系統中,一致性(Consistency)、可用性(Availability)和分割槽容忍性(Partition Tolerance)3 個要素最多隻能同時滿足兩個,不可兼得。其中,分割槽容忍性又是不可或缺的。

  • 一致性:分散式環境下多個節點的資料是否強一致。
  • 可用性:分散式服務能一直保證可用狀態。當用戶發出一個請求後,服務能在有限時間內返回結果。
  • 分割槽容忍性:特指對網路分割槽的容忍性。

舉例:Cassandra、Dynamo 等,預設優先選擇AP,弱化C;HBase、MongoDB 等,預設優先選擇CP,弱化A。

2、BASE 理論

核心思想:

  • 基本可用(Basically Available):指分散式系統在出現故障時,允許損失部分的可用性來保證核心可用。
  • 軟狀態(Soft State):指允許分散式系統存在中間狀態,該中間狀態不會影響到系統的整體可用性。
  • 最終一致性(Eventual Consistency):指分散式系統中的所有副本資料經過一定時間後,最終能夠達到一致的狀態。

二 一致性模型

資料的一致性模型可以分成以下 3 類:

  1. 強一致性:資料更新成功後,任意時刻所有副本中的資料都是一致的,一般採用同步的方式實現。
  2. 弱一致性:資料更新成功後,系統不承諾立即可以讀到最新寫入的值,也不承諾具體多久之後可以讀到。
  3. 最終一致性:弱一致性的一種形式,資料更新成功後,系統不承諾立即可以返回最新寫入的值,但是保證最終會返回上一次更新操作的值。

分散式系統資料的強一致性、弱一致性和最終一致性可以通過Quorum NRW演算法分析。

三 分散式事務

分散式事務的目的是保障分散式儲存中資料一致性,而跨庫事務會遇到各種不可控制的問題,如個別節點宕機,像單機事務一樣的ACID是無法奢望的。

1、Two/Three Phase Commit

2PC,中文叫兩階段提交。在分散式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的元件來統一掌控所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交。 兩階段提交的演算法如下:

第一階段:

  1. 協調者會問所有的參與者結點,是否可以執行提交操作。
  2. 各個參與者開始事務執行的準備工作:如:為資源上鎖,預留資源。
  3. 參與者響應協調者,如果事務的準備工作成功,則迴應“可以提交”,否則迴應“拒絕提交”。

第二階段:

  • 如果所有的參與者都回應“可以提交”,那麼,協調者向所有的參與者傳送“正式提交”的命令。參與者完成正式提交,並釋放所有資源,然後迴應“完成”,協調者收集各結點的“完成”迴應後結束這個Global Transaction。
  • 如果有一個參與者迴應“拒絕提交”,那麼,協調者向所有的參與者傳送“回滾操作”,並釋放所有資源,然後迴應“回滾完成”,協調者收集各結點的“回滾”迴應後,取消這個Global Transaction。

兩段提交最大的問題就是第3)項,如果第一階段完成後,參與者在第二階沒有收到決策,那麼資料結點會進入“不知所措”的狀態,這個狀態會block住整個事務。也就是說,協調者Coordinator對於事務的完成非常重要,Coordinator的可用性是個關鍵。

因些,我們引入三段提交,三段提交在Wikipedia上的描述如下,他把二段提交的第一個段break成了兩段:詢問,然後再鎖資源。最後真正提交。三段提交的核心理念是:在詢問的時候並不鎖定資源,除非所有人都同意了,才開始鎖資源。但三階段提交也存在一些缺陷,要徹底從協議層面避免資料不一致,可以採用Paxos或者Raft 演算法

目前兩階段提交、三階段提交存在如下的侷限性,並不適合在微服務架構體系下使用:

  • 所有的操作必須是事務性資源(比如資料庫、訊息佇列、EJB元件等),存在使用侷限性(微服務架構下多數使用HTTP協議),比較適合傳統的單體應用;

  • 由於是強一致性,資源需要在事務內部等待,效能影響較大,吞吐率不高,不適合高併發與高效能的業務場景;

2、Try Confirm Cancel(TCC)

一個完整的TCC業務由一個主業務服務和若干個從業務服務組成,主業務服務發起並完成整個業務活動,TCC模式要求從服務提供三個介面:Try、Confirm、Cancel。

  1. Try:完成所有業務檢查,預留必須業務資源。
  2. Confirm:真正執行業務,不作任何業務檢查;只使用Try階段預留的業務資源;Confirm操作滿足冪等性。

  3. Cancel:釋放Try階段預留的業務資源;Cancel操作滿足冪等性。

整個TCC業務分成兩個階段完成:

第一階段:主業務服務分別呼叫所有從業務的try操作,並在活動管理器中登記所有從業務服務。當所有從業務服務的try操作都呼叫成功或者某個從業務服務的try操作失敗,進入第二階段。

第二階段:活動管理器根據第一階段的執行結果來執行confirm或cancel操作。如果第一階段所有try操作都成功,則活動管理器呼叫所有從業務活動的confirm操作。否則呼叫所有從業務服務的cancel操作。

與2PC比較:

  • 位於業務服務層而非資源層。
  • 沒有單獨的準備(prepare)階段,Try操作兼備資源操作與準備能力。
  • Try操作可以靈活選擇業務資源的鎖定粒度。
  • 開發成本較高。

缺點:

  • Canfirm和Cancel的冪等性很難保證。
  • 這種方式缺點比較多,通常在複雜場景下是不推薦使用的,除非是非常簡單的場景,非常容易提供回滾Cancel,而且依賴的服務也非常少的情況。
  • 這種實現方式會造成程式碼量龐大,耦合性高。而且非常有侷限性,因為有很多的業務是無法很簡單的實現回滾的,如果序列的服務很多,回滾的成本實在太高。

3、非同步確保最終一致性

核心思想:

eBay 的架構師Dan Pritchett,曾在一篇解釋BASE 原理的論文《Base:An Acid Alternative》中提到一個eBay 分散式系統一致性問題的解決方案。它的核心思想是將需要分散式處理的任務通過訊息或者日誌的方式來非同步執行,訊息或日誌可以存到本地檔案、資料庫或訊息佇列,再通過業務規則進行失敗重試,它要求各服務的介面是冪等的。

本地訊息表

其基本的設計思想是將遠端分散式事務拆分成一系列的本地事務。如果不考慮效能及設計優雅,藉助關係型資料庫中的表即可實現。

舉個經典的跨行轉賬的例子來描述。

第一步虛擬碼如下,扣款100,通過本地事務保證了憑證訊息插入到訊息表中:

begin transaction:
  update User set account = account - 100 where userId = 'A'
  insert into message(msgId, userId, amount, status) values('123','A', 100, 1)
commit transaction

第二步,通知對方銀行賬戶上加100了。那問題來了,如何通知到對方呢?

通常採用兩種方式:

  1. 採用時效性高的MQ,由對方訂閱訊息並監聽,有訊息時自動觸發事件。
  2. 採用定時輪詢掃描的方式,去檢查訊息表的資料。

兩種方式其實各有利弊,僅僅依靠MQ,可能會出現通知失敗的問題。而過於頻繁的定時輪詢,效率也不是最佳的(90%是無用功)。所以,我們一般會把兩種方式結合起來使用。

解決了通知的問題,又有新的問題了。萬一這訊息有重複被消費,往使用者帳號上多加了錢,那豈不是後果很嚴重?其實我們可以訊息消費方也通過一個“消費狀態表”來記錄消費狀態。在執行“加款”操作之前,檢測下該訊息(提供標識)是否已經消費過,消費完成後,通過本地事務控制來更新這個“消費狀態表”。這樣子就避免重複消費的問題:

get msgId = '123';
check if mgsId is in message_applied(msgId);
if not applied:
    begin transaction:
        update User set account = account + 100 where userId = 'B'
        insert into message_applied(msgId) values('123')
    commit transaction

上訴的方式是一種非常經典的實現,基本避免了分散式事務,實現了“最終一致性”。但是,關係型資料庫的吞吐量和效能方面存在瓶頸,頻繁的讀寫訊息會給資料庫造成壓力。所以,在真正的高併發場景下,該方案也會有瓶頸和限制的。

MQ(非事務訊息)

通常情況下,在使用非事務訊息支援的MQ產品時,我們很難將業務操作與對MQ的操作放在一個本地事務域中管理。還是以上述提到的“跨行轉賬”為例,我們很難保證在扣款完成之後對MQ投遞訊息的操作就一定能成功。這樣一致性似乎很難保證。

我們來分析下可能的情況:

  1. 操作資料庫成功,向MQ中投遞訊息也成功,皆大歡喜。
  2. 操作資料庫失敗,不會向MQ中投遞訊息了。
  3. 操作資料庫成功,但是向MQ中投遞訊息時失敗,向外丟擲了異常,剛剛執行的更新資料庫的操作將被回滾。

從上面分析的幾種情況來看,貌似問題都不大的。那麼我們來分析下消費者端面臨的問題:

  1. 訊息出列後,消費者對應的業務操作要執行成功。如果業務執行失敗,訊息不能失效或者丟失。需要保證訊息與業務操作一致。
  2. 儘量避免訊息重複消費。如果重複消費,也不能因此影響業務結果。

如何保證訊息與業務操作一致,不丟失?

主流的MQ產品都具有持久化訊息的功能。如果消費者宕機或者消費失敗,都可以執行重試機制的(有些MQ可以自定義重試次數)。

如何避免訊息被重複消費造成的問題?

  1. 保證消費者呼叫業務的服務介面的冪等性。
  2. 通過消費日誌或者類似狀態表來記錄消費狀態,便於判斷(建議在業務上自行實現,而不依賴MQ產品提供該特性)。

這種方式比較常見,效能和吞吐量是優於使用關係型資料庫訊息表的方案。如果MQ自身和業務都具有高可用性,理論上是可以滿足大部分的業務場景的。不過在沒有充分測試的情況下,不建議在交易業務中直接使用。

MQ(事務訊息)

舉個例子,Bob向Smith轉賬,那我們到底是先發送訊息,還是先執行扣款操作?

好像都可能會出問題。如果先發訊息,扣款操作失敗,那麼Smith的賬戶裡面會多出一筆錢。反過來,如果先執行扣款操作,後傳送訊息,那有可能扣款成功了但是訊息沒發出去,Smith收不到錢。除了上面介紹的通過異常捕獲和回滾的方式外,還有沒有其他的思路呢?

下面以阿里巴巴的RocketMQ中介軟體為例,分析下其設計和實現思路。

RocketMQ第一階段傳送Prepared訊息時,會拿到訊息的地址,第二階段執行本地事物,第三階段通過第一階段拿到的地址去訪問訊息,並修改狀態。細心的讀者可能又發現問題了,如果確認訊息傳送失敗了怎麼辦?RocketMQ會定期掃描訊息叢集中的事物訊息,這時候發現了Prepared訊息,它會向訊息傳送者確認,Bob的錢到底是減了還是沒減呢?如果減了是回滾還是繼續傳送確認訊息呢?RocketMQ會根據傳送端設定的策略來決定是回滾還是繼續傳送確認訊息。這樣就保證了訊息傳送與本地事務同時成功或同時失敗。如下圖:

各大知名的電商平臺和網際網路公司,幾乎都是採用類似的設計思路來實現“最終一致性”的。這種方式適合的業務場景廣泛,而且比較可靠。不過這種方式技術實現的難度比較大。目前主流的開源MQ(ActiveMQ、RabbitMQ、Kafka)均未實現對事務訊息的支援,所以需二次開發或者新造輪子。比較遺憾的是,RocketMQ事務訊息部分的程式碼也並未開源,需要自己去實現。

總結:

閱讀了不少這方面的文章,在此基礎上,總結一下分散式事務一致性的解決方案。分散式系統的事務一致性本身就是一個技術難題,目前沒有一種很簡單很完美的方案能夠應對所有場景。分散式系統的一個難點就是因為“網路通訊的不可靠”,只能通過“確認機制”、“重試機制”、“補償機制”等各方面來解決一些問題。在綜合考慮可用性、效能、實現複雜度等各方面的情況上,比較好的選擇是“非同步確保最終一致性”,只是具體實現方式上有一些差異。

參考:

程立:《大規模SOA系統中的分佈事務處事》

相關推薦

訊息中介軟體(一)分散式系統事務一致性解決方案大對比,誰最好使?(轉)

原文轉載至:https://blog.csdn.net/lovesomnus/article/details/51785108   在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,

訊息中介軟體(一)分散式系統事務一致性解決方案大對比,誰最好使?

在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的Bob給Smith轉賬的案例。傳統的企業開發,

分散式系統事務一致性

一 分散式系統特點 現今網際網路界,分散式系統和微服務架構盛行。業界著名的CAP理論也告訴我們,在設計和實現一個分散式系統時,需要將資料一致性、系統可用性和分割槽容忍性放在一起考慮。 1、CAP理論 在分散式系統中,一致性(Consistency)、可用性(Availability)和分割槽容忍

分散式系統事務一致性解決方案

開篇 在OLTP系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的Bob給Smith轉賬的案例。傳統的企業開發,系統往往是以單體應用形式存在的,也沒有橫跨多個數據庫。我們通常只需藉助開發平臺中特有資料訪問技術和框架(例如Spring、JD

分散式系統事務一致性到CAP,BASE理論

首先,要聊的就是資料庫事務四大特性(簡稱ACID)      1、原子性(Atomicity):事務的原子性是指事務中的程式作為資料庫的邏輯工作單元,要麼全部成功,要麼全部失敗。      2、一致性(Consistency):事務一致性是指事務執行之前和執行之後資料保持一

分布式系統事務一致性解決方案

基本 插入 關系型 悲劇 win 比較 -1 返回結果 轉賬 開篇 在OLTP系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的Bob給Smith轉賬的案例。傳統的企業開發,系統往往是以單體應用形式存在的,也沒有橫跨多個數據庫。我們通常只需借助開發平臺

分布式系統事務一致性解決方案(轉)

跨庫 sources body 情況下 jpg 分庫 ability 開源 數據 本文首發於InfoQ,版權所有,請勿轉載!!!http://www.infoq.com/cn/articles/solution-of-distributed-system-transacti

分布式系統事務一致性

自身 roc 原理 會有 異步消息 body htm 可見 pre 單數據庫一致性: 1. 利用事務 分布式系統事務一致性: 1. 本地事務消息隊列:兩段提交,利用本地事務保證消息的可靠性 生產者: 1). 在數據庫(mysql)增加一個消息表,將本地數

分散式學習筆記三:分散式系統session一致性的問題

session的概念 什麼是session? 伺服器為每個使用者建立一個會話,儲存使用者的相關資訊,以便多次請求能夠定位到同一個上下文。這樣,當用戶在應用程式的 Web 頁之間跳轉時,儲存在 Session 物件中的變數將不會丟失,而是在整個使用者會話中一直存在下去。當用戶請求來自應用程式的

分散式系統session一致性的問題

session的概念 什麼是session? 伺服器為每個使用者建立一個會話,儲存使用者的相關資訊,以便多次請求能夠定位到同一個上下文。這樣,當用戶在應用程式的 Web 頁之間跳轉時,儲存在 Session 物件中的變數將不會丟失,而是在整個使用者會話中一直存在下去。當用

網際網路分散式系統Session一致性問題解析

1. 什麼是Session? 使用者使用網站的服務,需要使用瀏覽器與Web伺服器進行多次互動。HTTP協議本身是無狀態的,需要基於HTTP協議支援會話狀態(Session State)的機制。具體的實現方式是:在會話開始時,分配一個  唯一的會話標識(SessionID)

談談分散式系統一致性

What is Consistency 一致性(Consistency)一直是分散式系統裡一個很重要的話題。 在儲存系統中,為了避免資料丟失,我們都會對資料進行持久化。 對資料進行持久化可以避免宕機帶來的資料丟失問題,但是不能解決單機永久性故障的問題。儲存系統作為基礎設施,在單機上持久化是遠遠不夠的

分散式系統Session一致性問題

session的概念 什麼是session? 伺服器為每個使用者建立一個會話,儲存使用者的相關資訊,以便多次請求能夠定位到同一個上下文。這樣,當用戶在應用程式的 Web 頁之間跳轉時,儲存在 Session 物件中的變數將不會丟失,而是在整個使用者會話中一直存

架構文摘:分散式系統Session一致性問題解析

一、問題的提出 1. 什麼是Session? 使用者使用網站的服務,需要使用瀏覽器與Web伺服器進行多次互動。HTTP協議本身是無狀態的,需要基於HTTP協議支援會話狀態(Session State)的機制。具體的實現方式是:在會話開始時,分配一個 唯

什麼是分散式系統資料一致性

這次準備聊聊分散式系統中的關注點:一致性問題。文章中間穿插著輸出一些產品、運營、以及個人的深度思考。 本文從普遍認為的分散式系統中,最最最重要的資料一致性開始。內容適合人群>=0年技術相關經驗。 01、為什麼需要分散式系統? 任何

分散式系統事務

在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 寫在前面 在 OLTP 系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的 Bob 給

保證分散式系統資料一致性的6種方案

編者按:本文由「高可用架構後花園」群討論整理而成。 有人的地方,就有江湖 有江湖的地方,就有紛爭 問題的起源 在電商等業務中,系統一般由多個獨立的服務組成,如何解決分散式呼叫時候資料的一致性?  具體業務場景如下,比如一個業務操作,如果同時呼叫服務 A、B、C,需要滿足要麼同時成功;要麼同時失敗。A

分散式系統資料一致性的6種方案(轉)

                                                                                問題的起源 在電商等業務中,系統一般由多個獨立的服務組成,如何解決分散式呼叫時候資料的一致性?  具體

分散式系統最終一致性的防護欄---冪等

實踐證明,在分散式系統,同時滿足CAP定律(一致性、可用性、分割槽容錯性)是不太可能的。雖然強一致性可以提高使用者的體驗,但是犧牲了系統的可用性,在經過綜合的考慮和驗證下,業界普遍的做法是在一致性和可用性進行了平衡,也就是提高系統的可用性,保證系統的最終一致性。而系統的冪等

分散式系統一致性原理

對於分散式系統,我們必須深刻理解和牢記一點:分散式系統的不可靠性。 “可靠性”是指系統可以無故障的持續執行,如果一個系統在執行中意外宕機或者無法正常使用,那麼他就是一個不可靠的系統,即使宕機和無法使用的時間很短。我們知道,分散式系統通常是由獨立的伺服器通過網路