這樣理解分布式事務你是不是就會懂了?

2020-09-22 Java架構師公社

分布式事務主要解決分布式一致性的問題。說到底就是數據的分布式操作導致僅依靠本地事務無法保證原的性。與單機版的事務不同的是,單機是把多個命令打包成一個統一處理,分布式事務是將多個機器上執行的命令打包成一個命令統一處理。

常見的分布式事務場景

CAP 定理

傳統的 ACID 模型肯定無法解決分布式環境下的挑戰,基於此加州大學伯克利分校 Eric Brewer教授提出 CAP 定理,他指出 現代 WEB 服務無法同時滿足以下 3 個屬性:

  • 一致性(Consistency) : 所有的客戶端都能返回最新的操作。
  • 可用性(Availability) : 非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。
  • 分區容錯性(Partition tolerance) : 即使出現單個組件無法可用,操作依然可以完成。

關於一致性的理解後面分出來三個方向:

  • 強一致:任何一次讀都能讀到某個數據的最近一次寫的數據。系統中的所有進程,看到的操作順序,都和全局時鐘下的順序一致。簡言之,在任意時刻,所有節點中的數據是一樣的。
  • 弱一致:數據更新後,如果能容忍後續的訪問只能訪問到部分或者全部訪問不到,則是弱一致性。
  • 最終一致:不保證在任意時刻任意節點上的同一份數據都是相同的,但是隨著時間的遷移,不同節點上的同一份數據總是在向不同的方向變化。簡單說,就是在一段時間後,節點間的數據會最終達到一致狀態。

關於一致性的理解不同,後面對於 CAP 理論的實現就有所不同。

另外 Eric Brewer教授指出現代 WEB 服務無法同時滿足這 3 個屬性,說的是無法同時滿足,那這是為什麼呢?

如果在某個分布式系統中無副本,那麼必然滿足強一致性,同時也滿足可用性,但是如果這個數據宕機了,那麼可用性就得不到保證。

如果一個系統滿足 AP,那麼一致性又得不到保證。所以 CAP 原則的精髓就是要麼 AP,要麼 CP,要麼 AC,但是不存在 CAP。

BASE 定理

基於前面提到的 CAP,反正我們都無法同時滿足CAP,設計系統的最高目的就是讓他跑下去不出錯,那麼是不是可以不要求強一致性,最終讓他一致即可。所以後面又提出來了 BASE 定理:

  • Basically Available(基本可用)
  • Soft state(軟狀態)
  • Eventually consistent(最終一致性)

基於現在大型分布式系統的複雜性,我們無法保證服務永遠達到999,那麼是否可以取捨,核心服務達到999,非核心服務允許掛為了保全核心服務。另外在非核心服務 down 機過程中允許系統暫時出現不一致但是這個不一致並不影響系統的核心功能使用。

最終系統恢復,所有服務一起修複數據,最終達到一致的狀態。

業內通常把嚴格遵循 ACID 的事務稱為剛性事務,而基於 BASE 思想實現的事務稱為柔性事務。柔性事務並不是完全放棄了 ACID,僅僅是放寬了一致性要求:事務完成後的一致性嚴格遵循,事務中的一致性可適當放寬。

常見的分布式事務實現方案

本地消息表最初是由eBay架構師Dan Pritchett在一篇解釋 BASE 原理的論文《Base:An Acid Alternative》(https://queue.acm.org/detail.cfm?id=1394128)中提及的,業界目前使用這種方案是比較多的,其核心思想是將分布式事務拆分成本地事務進行處理。

方案通過在事務主動發起方額外新建事務消息表,事務發起方處理業務和記錄事務消息在本地事務中完成,輪詢事務消息表的數據發送事務消息,事務被動方基於消息中間件消費事務消息表中的事務。

基於本地消息表的方案,每個事務發起方都需要額外新建事務消息記錄表,用於記錄分布式事務的消息的發生、處理狀態。

事務發起方在處理完業務邏輯之後需要將當前事務保存在消息表中,之後將消息發送到消息中間件中,並將消息的狀態設置為 「發送中」。

如果消息在投遞過程中丟失怎麼辦呢?事務發起方可以設置一個定時任務主動掃描狀態為 「發送中」 的消息重新投送。只有消息被業務方消費完畢返回消費成功的結果才確認成功並將消息狀態改為「已發送」。

這裡因為網絡異常或者發送異常導致一個消息可能會被重複發送,所以要求接收方要做到冪等性,允許重複消費。

這種方案的好處就是方案簡單,成本較低,實現也不複雜。

但是壞處也有很多,比如通過消息的方式延遲不好控制;本地消息表與業務耦合在一起沒有做到通用性;本地消息表基於資料庫來實現,有一定的瓶頸。

事務消息

Saga是什麼?Saga的定義是 「長時間活動的事務 」(Long Lived Transaction,後文簡稱為LLT)。他是普林斯頓大學 HECTOR GARCIA-MOLINA 教授在1987年的一篇關於分布式資料庫的論文中提出來的概念。

Long Lived 從字面意義上不清晰,Long 到底意味著多長?事務持續時間是一個小時、一天甚至一周嗎?其實都不是,時間跨度並不重要。重要的是什麼?關鍵的是跨系統的多次「事務」,Saga 往往由多個外部的事務構成,需要通過多次外部系統的消息交互,才能將整體事務從開始遷移到結束狀態,這和我們原來常見的在一個資料庫的短事務不一樣。比如一個旅行的訂單,是由機票、旅館、租車三個子訂單構成,都需要外部的確認,缺任何一個步驟,不能成行,這就是一個典型的 LLT。

看起來 Sage 的定義與別的分布式事務沒有什麼不同。分布式事務不就是多個不同的子事務構成一個整體嗎?再來看看 補償機制:

每個本地事務有相應的執行模塊和補償模塊,當 Sage 事務中的任意一個本地事務出錯, 可以通過調用相關事務對應的補償方法恢復,達到事務的最終一致性。

Saga 模型是把一個分布式事務拆分為多個本地事務,每個本地事務都有相應的執行模塊和補償模塊(對應TCC 中的 Confirm 和 Cancel),當 Saga 事務中任意一個本地事務出錯時,可以通過調用相關的補償方法恢復之前的事務,達到事務最終一致性。

由於 Saga 模型中沒有 Prepare 階段,因此事務間不能保證隔離性,當多個 Saga 事務操作同一資源時,就會產生更新丟失、髒數據讀取等問題,這時需要在業務層控制並發,例如:

  • 在應用層面加鎖;
  • 應用層面預先凍結資源。

Saga 恢復方式

Saga 支持向前和向後恢復:

  • 向後恢復:補償所有已完成的事務,如果任一的事務失敗;
  • 向前恢復:重試失敗的事務,假設每個子事務最終都會成功。

雖然 Saga 和 TCC 都是補償事務,但是由於提交階段不同,所以兩者也是有不同的:

  • Saga 沒有 Try 行為直接 Commit,所以會留下原始事務操作的痕跡,Cancel 屬於不完美補償,需要考慮對業務上的影響。TCC Cancel 是完美補償的 Rollback,補償操作會徹底清理之前的原始事務操作,用戶是感知不到事務取消之前的狀態信息的。
  • Saga 的補償操作通常可以異步執行,TCC 的 Cancel 和 Confirm 可以跟進需要是否異步化。
  • Saga 對業務侵入較小,只需要提供一個逆向操作的 Cancel 即可;而 TCC 需要對業務進行全局性的流程改造。
  • TCC 最少通信次數為 2n,而 Saga 為 n(n=子事務的數量)。

因為也是採用補償機制,那麼必然要求服務保持冪等性,如果服務調用超時需要通過冪等性來避免多次請求帶來的問題。

事務特性的滿足:

原子性:Saga 協調器保證整體事務要麼全部執行成功,要麼全部回滾。

一致性:Sage 保證最終一致性。

持久性:Saga 將整體事務拆分成獨立的本地事務,所以持久性在本地事務中很好實現。

但是隔離性 Saga 無法實現,因為大事務被拆分為多個小事務,每個事務提交的時機不同很難保證已提交的小事務不被別人可見。

目前業界提供兩類 Saga 的實現方式:

  • 一種是集中式協調的實現方式。集中式協調方式就是通過一個 Saga 對象來追蹤所有的 Saga 子任務的調用,由它來管理,追蹤整個事務是否應該提交或補償。這種方式帶來的缺點就是這種協調方式必然要與第一個Saga 事務耦合,即與業務耦合在一起。
  • 一種是分布式實現方式。分布式協調方式肯定就能避免耦合的問題。分布式實現的方案也很多,比如通過事件機制來實現,一條 Saga 事務鏈上的所有事務都訂閱同一個事件,如果失敗則通過失敗對應的事件消息來回滾即可。這種方式帶來的好處肯定是顯而易見的,但是也會有另一個問題,多個事件帶來的肯定是高並發的處理,那麼會不會因為多個事件處理相關的問題帶來一些循環依賴的問題。

開源分布式事務框架簡介#

Seata

Seata(Simple Extensible Autonomous Transaction Architecture,簡單可擴展自治事務框架)是 2019 年 1 月份螞蟻金服和阿里巴巴共同開源的分布式事務解決方案。

Seata 會有 4 種分布式事務解決方案,分別是 AT 模式、TCC 模式、Saga 模式和 XA 模式。

XA 模式

XA 模式是 Seata 將會開源的另一種無侵入的分布式事務解決方案,任何實現了 XA 協議的資料庫都可以作為資源參與到分布式事務中,目前主流資料庫,例如 MySql、Oracle、DB2、Oceanbase 等均支持 XA 協議。

XA 協議有一系列的指令,分別對應一階段和二階段操作。「xa start」 和 「xa end」 用於開啟和結束XA 事務;「xa prepare」 用於預提交 XA 事務,對應一階段準備;「xa commit」和「xa rollback」用於提交、回滾 XA 事務,對應二階段提交和回滾。

在 XA 模式下,每一個 XA 事務都是一個事務參與者。分布式事務開啟之後,首先在一階段執行「xa start」、「業務 SQL」、「xa end」和 「xa prepare」 完成 XA 事務的執行和預提交;二階段如果提交的話就執行 「xa commit」,如果是回滾則執行「xa rollback」。這樣便能保證所有 XA 事務都提交或者都回滾。

XA 模式下,用戶只需關注自己的「業務 SQL」,Seata 框架會自動生成一階段、二階段操作;XA 模式的實現如下:

  • 一階段:

在 XA 模式的一階段,Seata 會攔截「業務 SQL」,在「業務 SQL」之前開啟 XA 事務(「xa start」),然後執行「業務 SQL」,結束 XA 事務「xa end」,最後預提交 XA 事務(「xa prepare」),這樣便完成 「業務 SQL」的準備操作。

  • 二階段提交:

執行「xa commit」指令,提交 XA 事務,此時「業務 SQL」才算真正的提交至資料庫。

  • 二階段回滾:

執行「xa rollback」指令,回滾 XA 事務,完成「業務 SQL」回滾,釋放資料庫鎖資源。

XA 模式下,用戶只需關注「業務 SQL」,Seata 會自動生成一階段、二階段提交和二階段回滾操作。XA 模式和 AT 模式一樣是一種對業務無侵入性的解決方案;但與 AT 模式不同的是,XA 模式將快照數據和行鎖等通過 XA 指令委託給了資料庫來完成,這樣 XA 模式實現更加輕量化。

AT 模式

AT 模式是一種無侵入的分布式事務解決方案。在 AT 模式下,用戶只需關注自己的「業務 SQL」,用戶的 「業務 SQL」 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。

AT 模式的一階段、二階段提交和回滾

均由 Seata 框架自動生成,用戶只需編寫「業務 SQL」,便能輕鬆接入分布式事務,AT 模式是一種對業務無任何侵入的分布式事務解決方案。

TCC 模式

2019 年 3 月份,Seata 開源了 TCC 模式,該模式由螞蟻金服貢獻。TCC 模式需要用戶根據自己的業務場景實現 Try、Confirm 和 Cancel 三個操作;事務發起方在一階段 執行 Try 方式,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。

TCC 三個方法描述:

  • Try:資源的檢測和預留;
  • Confirm:執行的業務操作提交;要求 Try 成功 Confirm 一定要能成功;
  • Cancel:預留資源釋放。

用戶接入 TCC 模式,最重要的事情就是考慮如何將業務模型拆成 2 階段,實現成 TCC 的 3 個方法,並且保證 Try 成功 Confirm 一定能成功。相對於 AT 模式,TCC 模式對業務代碼有一定的侵入性,但是 TCC 模式無 AT 模式的全局行鎖,TCC 性能會比 AT 模式高很多。

Saga 模式

Saga 模式是 Seata 即將開源的長事務解決方案,將由螞蟻金服主要貢獻。在 Saga 模式下,分布式事務內有多個參與者,每一個參與者都是一個衝正補償服務,需要用戶根據業務場景實現其正向操作和逆向回滾操作。

分布式事務執行過程中,依次執行各參與者的正向操作,如果所有正向操作均執行成功,那麼分布式事務提交。如果任何一個正向操作執行失敗,那麼分布式事務會去退回去執行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分布式事務回到初始狀態。

Saga 模式下分布式事務通常是由事件驅動的,各個參與者之間是異步執行的,Saga 模式是一種長事務解決方案。

ServiceComb

ServiceComb 是華為開源的微服務框架,目前已升級為 Apache 頂級項目。 準確來說它並不是一個純粹的分布式事務框架而是微服務框架,最開始的版本是 Go 語言,後面支持了 Java。

ServiceComb 由 3 個子項目組成:

  • java-chassis:服務治理
  • service-center:服務註冊
  • saga:分布式事務解決

從名字上看很顯然是基於 Saga 模式開發的柔性事務方案。Saga系統分為兩部分:Alpha 和 Omega。Alpha 是獨立的服務,扮演事務協調器的作用。Omega 作為開發組件,和業務進程運行在一起。

Omega 會以切面編程的方式向應用程式注入相關的處理模塊。這裡有攔截請求的模塊, 用來幫助我們構建分布式事務調用的上下文。 同時在事務處理初始階段處理事務的相關準備的操作,例如創建 Saga 起始事件,以及相關的的起始事件, 根據事務的執行的成功或者失敗生產相關的事務終止或者失敗事件。

Omega 會與 Alpha 進行連結會把這些事件通知給 Alpha。 Alpha 可以在後臺進行分析,根據 Saga 事務執行的情況給 Omega 下達相關的指令進行相關的回滾恢復。

這樣設計的好處是 Saga 實現代碼與用戶的代碼分離, 用戶只需要添加幾個 annotation,Saga 實現就能 Saga 事件的執行情況並進行相關的處理。

作者: rickiyang

原文連結:https://www.cnblogs.com/rickiyang/p/13704868.html

如果感覺本文對你有幫助,幫忙關注轉發支持一下

相關焦點

  • 深入理解分布式事務
    1、什麼是分布式事務分布式事務就是指事務的參與者、支持事務的伺服器、資源伺服器以及事務管理器分別位於不同的分布式系統的不同節點之上。以上是百度百科的解釋,簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分布在不同的伺服器上,且屬於不同的應用,分布式事務需要保證這些小操作要麼全部成功,要麼全部失敗。本質上來說,分布式事務就是為了保證不同資料庫的數據一致性。
  • 不懂分布式事務,別說你懂微服務
    由於多個數據源的同時訪問,事務需要跨多個數據源管理,分布式事務應運而生。其中最流行的就是兩階段提交(2PC),分布式事務由事務管理器(TM)統一管理。兩階段提交分為準備階段和提交階段。具體分布式事務2PC和3PC的詳細介紹請見 關於分布式事務、兩階段提交協議、三階提交協議。分布式事務不是本文的重點,故不展開。2. 微服務下的事務管理那麼,分布式事務2PC或者3PC是否適合於微服務下的事務管理呢?
  • 分布式事務和分布式hash
    NeverTh | 作者urlify.cn/fM36be | 來源分布式事務是什麼?分布式事務就是保證各個微服務之間數據一致,本質上就是保證不同資料庫的數據一致性。大致流程:準備階段 向各個參與者發送準備命令,可以理解為把除了提交事務之外的事情都做好。所有參與者都返回準備成功則下一階段提交事務,否則下一階段協調者就會向所有參與者發送回滾事務的請求,即分布式事務執行失敗。提交階段 可能提交事務也可能回滾事務,並且存在回滾失敗或者提交失敗,失敗之後就會不斷重試。
  • 字節跳動面試官這樣問消息隊列:分布式事務、重複消費、順序消費
    強校驗:比如你監聽到用戶支付成功的消息,你監聽到了去加GMV是不是要調用加錢的接口,那加錢接口下面再調用一個加流水的接口,兩個放在一個事務,成功一起成功失敗一起失敗。這裡很好理解,一個訂單你發送的時候放到一個隊列裡面去,你同一個的訂單號Hash一下是不是還是一樣的結果,那肯定是一個消費者消費,那順序是不是就保證了?真正的順序消費不同的中間件都有自己的不同實現我這裡就舉個例子,大家思路理解下。
  • 女朋友問敖丙:什麼是分布式事務?
    不過暖男為了保證文章的完整性確保所有人都聽得懂,我還是得先說說 ACID,然後再來介紹下什麼是分布式事務和常見的分布式事務包括 2PC、3PC、TCC、本地消息表、消息事務、最大努力通知。事務嚴格意義上的事務實現應該是具備原子性、一致性、隔離性和持久性,簡稱 ACID。
  • 分布式事務還不理解?這一篇帶你走進它的世界
    核心思想就是對每一個事務都採用先嘗試後提交的處理方式,處理後所有的讀操作都要能獲得最新的數據,因此也可以將二階段提交看作是一個強一致性算法。處理流程簡單一點理解,可以把協調者節點比喻為帶頭大哥,參與者理解比喻為跟班小弟,帶頭大哥統一協調跟班小弟的任務執行。
  • 透徹,分布式事務一網打盡
    ,你可以認為除了事務的提交啥都做了。事務協調者在第一階段未收到個別參與者的響應,則等待一定時間就會認為事務失敗,會發送回滾命令,所以在 2PC 中事務協調者有超時機制。我們再來分析一下 2PC 的優缺點。
  • 分布式事務方案 - SAGA模式
    __biz=MzA4Nzc4MjI4MQ==&mid=2652404032&idx=1&sn=f3e7d518e7cbbe797d4eefbf355e27da本文目的是講清楚 SAGA 這種分布式事務解決方案的實現思路,
  • 12張圖帶你徹底理解分布式事務產生的場景和解決方案
    不過,這位小夥伴還是挺樂觀的,讓我寫寫關於【分布式事務】的系列文章,想提升自己關於分布式事務的短板,那我就寫一個【分布式事務】專題吧,專題的內容計劃是從原理、框架源碼到企業級實現,這篇文章也算是整個專題的開篇吧。希望能夠為小夥伴們帶來實質性的幫助。本地事務本地事務流程在介紹分布式事務之前,我們先來看看本地事務。首先,我們先來一張圖。
  • 大廠面試系列(九):MQ和分布式事務
    你了解那些具體的消息中間件產品?mq的消費端是怎麼處理的? 整理一下你的消費端的整個處理邏輯流程,然後說說你的ack是在哪裡返回的。按照你這樣畫的話,如果資料庫突然宕機,你的消息該怎麼確認已經接收? 那如果發送端的服務是多臺部署呢?你保存消息的時候資料庫就一直報唯一性的錯誤?rocketmq用在什麼場景。
  • 面試官:談談對分布式事務的一點理解和解決方案
    2、如果消息隊列中間件正常,消息正常推送,但是第3步由於SQL存在語法錯誤導致事務回滾,這樣就會出現了下遊微服務被調用成功,本地事務卻回滾的問題,導致了上下遊系統數據不一致。目前業界提供的解決方案業界目前主流的分布式事務解決方案主要有:多階段提交方案(2PC、3PC)、補償事務(TCC)和消息事務(主要是RocketMQ,基本思想也是多階段提交方案,並且基於中間提供件輪詢和重試,其他消息隊列中間件並沒有實現分布式事務)。
  • 兩天,我把分布式事務搞完了
    而和點名有所不同的是,老師發現某幾個學生不在還是能繼續上課,而我們的事務可不允許這樣。事務協調者在第一階段未收到個別參與者的響應,則等待一定時間就會認為事務失敗,會發送回滾命令,所以在 2PC 中事務協調者有超時機制。
  • 兩天,我把分布式事務搞完了!
    而和點名有所不同的是,老師發現某幾個學生不在還是能繼續上課,而我們的事務可不允許這樣。事務協調者在第一階段未收到個別參與者的響應,則等待一定時間就會認為事務失敗,會發送回滾命令,所以在 2PC 中事務協調者有超時機制。我們再來分析一下 2PC 的優缺點。
  • 阿里面試官沒想到分布式事務,我一口氣說了六種
    不過暖男為了保證文章的完整性確保所有人都聽得懂,我還是得先說說 ACID,然後再來介紹下什麼是分布式事務和常見的分布式事務包括 2PC、3PC、TCC、本地消息表、消息事務、最大努力通知。一致性(Consistency),可以理解為數據是滿足完整性約束的,也就是不會存在中間狀態的數據,比如你帳上有400,我帳上有100,你給我打200塊,此時你帳上的錢應該是200,我帳上的錢應該是300,不會存在我帳上錢加了,你帳上錢沒扣的中間狀態。
  • 一文看懂分布式事務
    如何解決場景舉例考慮這樣一種業務場景,系統 A 調用系統 B 的退款服務進行退款,系統 A 更改內部退款狀態,接著調用系統 C 的簡訊服務通知用戶。在這樣的一個場景下,由於網絡不可靠的必然存在,存在 A、B、C 三個系統之間一致性的問題。
  • 最全的分布式事務總結
    事務的定義 22. 資料庫本地事務四大特性 ACID 23. mysql InnoDB 實現原理 24. 什麼是分布式事務 35. 分布式事務產生的原因 46. 分布式事務的基礎理論 47. 分布式事務協議 58. 分布式常用解決方案 79.
  • 為了弄懂分布式「花了整整三天」,我把分布式事務搞完了
    ,每個參與者收到命令之後會執行相關事務操作,你可以認為除了事務的提交啥都做了。,參與者等半天沒收到協調者的情況的話就會自動提交事務。,致力於提供高性能和簡單易用的分布式事務服務。(可以理解為對這條數據的鎖),然後才能順利提交本地事務。
  • 又見分布式事務之阿里開源Seata
    Seata 的設計思路是將一個分布式事務可以理解成一個全局事務,下面掛了若干個分支事務,而一個分支事務是一個滿足 ACID 的本地事務,因此我們可以操作分布式事務像操作本地事務一樣。其中,TM是一個分布式事務的發起者和終結者,TC負責維護分布式事務的運行狀態,而RM則負責本地事務的運行。
  • Spring Boot整合分布式事務簡介
    什麼是分布式事務百度百科對分布式事務的解釋如下:分布式事務就是指事務的參與者、支持事務的伺服器、資源伺服器以及事務管理器分別位於分布式系統的不同節點之上。當資料庫的數據越來越大,資料庫無法承受起壓力,就會開始分庫分表,分庫分表後不同的庫就會分布在不同的伺服器上,明顯的就會出現數據一致性問題。或者同一個事務中要調用的不同系統的不同的庫,也要保證要不全都成功,要不全部回滾。
  • 5分鐘理解架構師必備的:分布式事務解決方案
    為了保證分布式環境下數據強一致性,需要引入分布式事務,而分布式事務由於網絡環境的不確定性,天生就很難實現分布式下,我想要強一致性為了保證分布式事務的正確性,目前網際網路領域有幾種流行的解決方案,但是大部分都沒有像XA事務一樣形成標準的工業規範。但是這些方案在某些特定的行業或者業務場景下卻得到了越來越多的開發者的認可。