微服務分布式事務4種解決方案實戰


分布式事務

  • 分布式事務是指事務的參與者,支持事務的服務器,資源服務器分別位於分布式系統的不同節點之上,通常一個分布式
    事物中會涉及到對多個數據源或業務系統的操作。

  • 典型的分布式事務場景:跨銀行轉操作就涉及調用兩個異地銀行服務

CAP理論

  • CAP理論:一個分布式系統不可能同時滿足一致性,可用性和分區容錯性這個三個基本需求,最多只能同時滿足其中兩

  • 一致性(C):數據在多個副本之間是否能夠保持一致的特性。

  • 可用性(A):是指系統提供的服務必須一致處於可用狀態,對於每一個用戶的請求總是在有限的時間內返回結果,超過時
    間就認為系統是不可用的

  • 分區容錯性(P):分布式系統在遇到任何網絡分區故障的時候,仍然需要能夠保證對外提供滿足一致性和可用性的服務,
    除非整個網絡環境都發生故障。

CAP定理的應用

  • 放棄P(CA):如果希望能夠避免系統出現分區容錯性問題,一種較為簡單的做法就是將所有的數據(或者是與事物先相關
    的數據)都放在一個分布式節點上,這樣雖然無法保證100%系統不會出錯,但至少不會碰到由於網絡分區帶來的負面影

  • 放棄A(CP):其做法是一旦系統遇到網絡分區或其他故障時,那受到影響的服務需要等待一定的時間,應用等待期間系統
    無法對外提供正常的服務,即不可用

  • 放棄C(AP):這里說的放棄一致性,並不是完全不需要數據一致性,是指放棄數據的強一致性,保留數據的最終一致性。

BASE理論

  • BASE是基本可用,軟狀態,最終一致性。是對CAP中一致性和可用性權限的結果,是基於CAP定理演化而來的,核心思
    想是即使無法做到強一致性,但每個應用都可以根據自身的業務特定,采用適當的方式來使系統達到最終一致性

2PC提交

  • 二階段提交協議是將事務的提交過程分成提交事務請求和執行事務提交兩個階段進行處理。

 

階段一:提交事務請求

 

  • 事務詢問:協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交操作,並開始等待各參與者的響應

  • 執行事務:各參與者節點執行事務操作,並將Undo和Redo信息記入事務日志中

  • 如果參與者成功執事務操作,就反饋給協調者Yes響應,表示事物可以執行,如果沒有成功執行事務,就反饋給協調者
    No響應,表示事務不可以執行

  • 二階段提交一些的階段一夜被稱為投票階段,即各參與者投票票表明是否可以繼續執行接下去的事務提交操作

 

階段二:執行事務提交

 

  • 假如協調者從所有的參與者或得反饋都是Yes響應,那么就會執行事務提交。

  • 發送提交請求:協調者向所有參與者節點發出Commit請求

  • 事務提交:參與者接受到Commit請求后,會正式執行事務提交操作,並在完成提交之后放棄整個事務執行期間占用的
    事務資源

  • 反饋事務提交結果:參與者在完成事物提交之后,向協調者發送ACK消息

  • 完成事務:協調者接收到所有參與者反饋的ACK消息后,完成事務

 

中斷事務

 

  • 假如任何一個參與者向協調者反饋了No響應,或者在等待超市之后,協調者尚無法接收到所有參與者的反饋響應,那么
    就中斷事務。

  • 發送回滾請求:協調者向所有參與者節點發出Rollback請求

  • 事務回滾:參與者接收到Rollback請求后,會利用其在階段一種記錄的Undo信息執行事物回滾操作,並在完成回滾之
    后釋放事務執行期間占用的資源。

  • 反饋事務回滾結果:參與則在完成事務回滾之后,向協調者發送ACK消息

  • 中斷事務:協調者接收到所有參與者反饋的ACk消息后,完成事務中斷、

 

優缺點

 

  • 原理簡單,實現方便

  • 缺點是同步阻塞,單點問題,腦裂,保守

 

3PC提交

  • 三階段提,也叫三階段提交協議,是二階段提交(2PC)的改進版本。

  • 與兩階段提交不同的是,三階段提交有兩個改動點。引入超時機制。同時在協調者和參與者中都引入超時機制。在第一
    階段和第二階段中插入一個准備階段。保證了在最后提交階段之前各參與節點的狀態是一致的。

  • 三階段提交就有CanCommit、PreCommit、DoCommit三個階段。

 

Seata分布式事務方案

  • Seata 是一款開源的分布式事務解決方案,致力於提供高性能和簡單易用的分布式事務服務。Seata 將為用戶提供了
     AT、TCC、SAGA 和 XA 事務模式,為用戶打造一站式的分布式解決方案。

Seata術語

  • TC:事務協調者。維護全局和分支事務的狀態,驅動全局事務提交或回滾。

  • TM:事務管理器。定義全局事務的范圍:開始全局事務、提交或回滾全局事務

  • RM:管理分支事務處理的資源,與TC交談以注冊分支事務和報告分支事務的狀態,並驅動分支事務提交或回滾。

Seata的2PC方案

  • 一階段:業務數據和回滾日志記錄在同一個本地事務中提交,釋放本地鎖和連接資源。

  • 二階段:提交異步化,非常快速地完成。回滾通過一階段的回滾日志進行反向補償。

  • 一階段本地事務提交前,需要確保先拿到 全局鎖 。拿不到全局鎖 ,不能提交本地事務。

  • 拿全局鎖的嘗試被限制在一定范圍內,超出范圍將放棄,並回滾本地事務,釋放本地鎖。

  • 在數據庫本地事務隔離級別讀已提交或以上的基礎上,Seata(AT 模式)的默認全局隔離級別是 讀未提交

  • 如果應用在特定場景下,必需要求全局的 讀已提交 ,目前 Seata 的方式是通過 SELECT FOR UPDATE 語句的代理。

Seata執行流程分析

  

  • 每個RM使用DataSourceProxy鏈接數據路,目的是使用ConnectionProxy,使用數據源和數據代理的目的是在第一階段
    將undo_log和業務數據放在一個本地事務提交,這樣就保存了只要有業務操作就一定有undo_log

  • 在第一階段undo_log中存放了數據修改前后修改后的值,為事務回滾做好准別,所以第一階段完成就已經將分支事務提
    交了,也就釋放了鎖資源

  • TM開啟全局事務開始,將XID全局事務ID放在事務上下文中,通過feign調用也將XID傳入下游分支事務,每個分支事務
    將自己的Branch ID 分支事務ID與XID關聯

  • 第二階段全局事務提交,TC會通知各分支參與者提交分支事務,在第一階段就已經提交了分支事務,這里各參與者只需
    要刪除undo_log即可,並且可以異步執行,第二階段很快可以完成

  • 如果某一個分支事務異常,第二階段就全局事務回滾操作,TC會通知各分支參與者回滾分支事務,通過XID和
    Branch-ID找到對應的回滾日志,通過回滾日志生成的反向SQL並執行,以完成分支事務回滾到之前

Seata的實戰案列

  • github.com/seata/seata…

  • github.com/seata/seata…

 

TCC分布式事務

  • TCC是服務化的兩階段編程模型,其Try、Confirm、Cancel,3個方法均由業務編碼實現

  • TCC要求每個分支事務實現三個操作:預處理Try,確認Confirm,撤銷Cancel。

  • Try操作做業務檢查及資源預留,

  • Confirm做業務確認操作

  • Cancel實現一個與Try相反的操作即回滾操作。

  • TM首先發起所有的分支事務Try操作,任何一個分支事務的Try操作執行失敗,TM將會發起所有分支事務的Cancel操作,
    若Try操作全部成功,TM將會發起所有分支事務的Confirm操作,其中Confirm/Cancel操作若執行失敗,TM會進行重試。

TCC的三個階段

  • Try階段是做業務檢查(一致性)及資源預留(隔離),此階段僅是一個初步操作,它和后續的Confirmy一起才能構成一個完整
    的業務邏輯

  • Confirm階段是做確認提交,Try階段所有分支事務執行成功后開始執行Confirm,通常情況下,采用TCC則認為
    Confirm階段是不會出錯的,即:只要Try成功,Confirm一定成功,若Confirm階段真的出錯,需要引入重試機制或人工
    處理

  • Cancel階段是在業務執行錯誤需要回滾到狀態下執行分支事務的取消,預留資源的釋放,通常情況下,采用TCC則認為
    Cancel階段也一定是真功的,若Cance階段真的出錯,需要引入重試機制或人工處理

  • TM事務管理器:TM事務管理器可以實現為獨立的服務,也可以讓全局事務發起方充當TM的角色,TM獨立出來是為了公
    用組件,是為了考慮系統結構和軟件的復用

  • TM在發起全局事務時生成全局事務記錄,全局事務ID貫穿整個分布式事務調用鏈條,用來記錄事務上下文,追蹤和記錄
    狀態,用於Confirm和cacel失敗需要進行重試,因此需要實現冪等

TCC的三種異常處理情況

冪等處理

  • 因為網絡抖動等原因,分布式事務框架可能會重復調用同一個分布式事務中的一個分支事務的二階段接口。所以分支事務
    的二階段接口Confirm/Cancel需要能夠保證冪等性。如果二階段接口不能保證冪等性,則會產生嚴重的問題,造成資源
    的重復使用或者重復釋放,進而導致業務故障。

  • 對於冪等類型的問題,通常的手段是引入冪等字段進行防重放攻擊。對於分布式事務框架中的冪等問題,同樣可以祭出
    這一利器。

  • 冪等記錄的插入時機是參與者的Try方法,此時的分支事務狀態會被初始化為INIT。然后當二階段的Confirm/Cancel執行
    時會將其狀態置為CONFIRMED/ROLLBACKED。

  • 當TC重復調用二階段接口時,參與者會先獲取事務狀態控制表的對應記錄查看其事務狀態。如果狀態已經為
    CONFIRMED/ROLLBACKED,那么表示參與者已經處理完其分內之事,不需要再次執行,可以直接返回冪等成功的結果
    給TC,幫助其推進分布式事務。

 

空回滾

  • 當沒有調用參與方Try方法的情況下,就調用了二階段的Cancel方法,Cancel方法需要有辦法識別出此時Try有沒有執行。如果Try還沒執行,表示這個Cancel操作是無效的,即本次Cancel屬於空回滾;如果Try已經執行,那么執行的是正常的回滾邏輯。

  • 要應對空回滾的問題,就需要讓參與者在二階段的Cancel方法中有辦法識別到一階段的Try是否已經執行。很顯然,可以
    繼續利用事務狀態控制表來實現這個功能。

  • 當Try方法被成功執行后,會插入一條記錄,標識該分支事務處於INIT狀態。所以后續當二階段的Cancel方法被調用時,
    可以通過查詢控制表的對應記錄進行判斷。如果記錄存在且狀態為INIT,就表示一階段已成功執行,可以正常執行回滾操
    作,釋放預留的資源;如果記錄不存在則表示一階段未執行,本次為空回滾,不釋放任何資源。

 

資源懸掛

  • 問題:TC回滾事務調用二階段完成空回滾后,一階段執行成功

  • 解決:事務狀態控制記錄作為控制手段,二階段發現無記錄時插入記錄,一階段執行時檢查記錄是否存在

 

TCC和2PC比較

  • 2PC通常都是在跨庫的DB層面,而TCC則在應用層面處理,需要通過業務邏輯實現,這種分布式事務的實現方式優勢在
    於,可以讓應用自己定義數據操作的粒度,使得降低鎖沖突,提高吞吐量成為可能

  • 而不足之處則在於對應用的侵入性非常強,業務邏輯的每個分支都需要實現Try,confirm,cancel三個操作。此外,其實
    現難度也比較大,需要按照網絡狀態,系統故障的不同失敗原因實現不同的回滾策略

 

Hmily框架實現TCC案列

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 賬戶A
try
     try 的冪等效驗
     try 的懸掛處理
     檢查余額是否夠 30
     扣減 30
     
     
confirm:
     空處理即可,通常TCC階段是認為confirm是不會出錯的
  
cancel:
     cancel冪等效驗
     cacel空回滾處理
     增加可用余額 30 元,回滾操作
     
     
# 賬戶B
  
try
     空處理即可
     
confirm:
     confirm的冪等效驗
     正式增加 30
cancel:
       空處理即可

 

RocketMQ實現可靠消息最終一致性

  • 可靠消息最終一致性就是保證消息從生產方經過消息中間件傳遞到消費方的一致性

  • RocketMQ主要解決了兩個功能:本地事務與消息發送的原子性問題。事務參與方接收消息的可靠性

  • 可靠消息最終一致性事務適合執行周期長且實時性要求不高的場景,引入消息機制后,同步的事務操作變為基於消息執行
    的異步操作,避免分布式事務中的同步阻塞操作的影響,並實現了兩個服務的解耦

  

最大努力通知

最大努力通知與可靠消息一致性有什么不同

  • 可靠消息一致性,發起通知方需要保證將消息發出去,並且將消息發送到接收通知方,消息的可靠性由發起通知方保證

  • 最大努力通知,發起通知方盡最大的努力將業務處理結果通知為接收通知方,但是消息可能接收不到,此時需要接收通知
    方主動調用發起通知方的接口查詢業務,通知可靠性關鍵在於接收通知方

兩者的應用場景

  • 可靠消息一致性關注的是交易過程的事務一致,以異步的方式完成交易

  • 最大努力通知關注的是交易后的通知事務,即將交易結果可靠的通知出去

 

基於MQ的ack機制實現最大努力通知

  

  • 利用MQ的ack機制由MQ向接收通知方發送消息通知,發起方將普通消息發送到MQ

  • 接收通知監聽MQ,接收消息,業務處理完成回應ACK

  • 接收通知方如果沒有回應ACK則MQ會重復通知,按照時間間隔的方式,逐步拉大通知間隔

  • 此方案適用於內部微服務之間的通知,不適應與通知外部平台

 

方案二:增加一個通知服務區進行通知,提供外部第三方時適用

  分布式事務方案對比分析

  • 2PC 最大的一個詬病是一個阻塞協議。RM在執行分支事務后需要等待TM的決定,此時服務會阻塞鎖定資源。由於其阻
    塞機制和最差時間復雜度高,因此,這種設計不能適應隨着事務涉及的服務數量增加而擴展的需要,很難用於並發較高以
    及子事務生命周期較長的分布式服務中

  • 如果拿TCC事務的處理流程與2PC兩階段提交做比較,2PC通常都是在跨庫的DB層面,而TCC則在應用層面處理,需要通
    過業務邏輯來實現。這種分布式事務的優勢在於,可以讓應用自定義數據操作的粒度,使得降低鎖沖突,提高吞吐量成為
    可能。而不足之處在於對應用的侵入性非常強,業務邏輯的每個分支都需要實現三個操作。此外,其實現難度也比較大,
    需要按照網絡狀態,系統故障等不同失敗原因實現不同的策略。

  • 可靠消息最終一致性事務適合執行周期長且實時性要求不高的場景。引入消息機制后,同步的事務操作變為基於消息執行
    的異步操作,避免了分布式事務中的同步阻塞操作的影響,並實現了兩個服務的解耦,典型的場景:注冊送積分,登陸送
    優惠券等

  • 最大努力通知是分布式事務中要求最低的一種,適用於一些最終一致性時間敏感度低的業務,允許發起通知方業務處理失
    敗,在接收通知方收到通知后積極進行失敗處理,無論發起通知方如何處理結果都不會影響到接收通知方的后續處理,發
    起通知方需提供查詢執行情況接口,用於接收通知方校對結果,典型的應用場景:銀行通知,支付結果通知等。

  2PC TCC 可靠消息 最大努力通知


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM