分布式事務 各方案的最通俗講解

2022-08-01 01:15:13 字數 3341 閱讀 3544

分布式事務的方案:

xa/tcc/本地訊息表/最大努力通知/可靠訊息最終一致性/(saga/seata)

1.xa(二段提交/2pc) :資料庫有支援xa的協議的,所以其實xa是在資料庫層面的操作,不是服務層面的操作

第一階段:詢問

第二階段:執行

一般是在多資料來源跨庫上執行~不適合在微服務架構上,微服務架構思想是每個微服務只執行乙個庫,需要呼叫業務只能通過暴露介面進行

---------------------------------- 

2.tcc(try-confirm-cancel)

try:主要是做檢查後續的操作能否執行,例如扣款的話需要鎖住金額同時檢視扣款餘額是否足夠等

confirm:執行具體的操作

cancel:是乙個補償機制需要寫補償邏輯,例如某乙個服務扣款失敗,某乙個成功,那麼成功的需要把原來扣取的款給加回去

特點:是跟業務嚴重的耦合和侵入,同樣的cancel不同業務實現都會不一樣,一般在嚴重需要一致性的場景才會使用tcc 例如跟資金相關的~

ps:tcc需要事務協調器來協助完成上面操作這些東西就不說了,都是實現細節,具體可以看對應的文章

----------------------------------

3.本地訊息表方案(ebay採用)

1)主動方和被動方都要在本地存乙個訊息表

2)主動方執行成功後在他的本地訊息表上同時插入一條訊息狀態為'待確認'(注意:主動執行方操作和本地訊息表的操作需要在同一事務上),同時傳送一條訊息到mq讓被動方消費,同時想辦法監聽被動方是否執行成功(輪訓或者基於zookeeper監聽)

3)被動方消費資料,先在本地訊息表插入資料,同時執行自己的業務(注意:被動方業務操作和本地訊息表在同一事務上,同時本地訊息表需要有唯一鍵保證不重複消費)

4)如果成功主動方更新自己的本地訊息表的狀態為'成功',否則定時輪訓'待確認'的訊息表知道傳送到mq上讓被動方執行

缺點:大量依賴本地訊息表

---------------------------------- 

4.最大努力通知方案

業務活動的主動方在完成處理之後向業務活動的被動方傳送訊息,允許訊息丟失。業務活動的被動方根據定時策略,向業務活動的主動方查詢,恢復丟失的業務訊息

---------------------------------- 

5.可靠訊息最終一致性方案(這個方案使用比較多,有點類似本地訊息表只不過訊息表放在mq,一般用於扣庫存)

1)就是基於mq的事務機制(rocketmq[rocketmq如果發現主動方成功了,傳送確認給mq時失敗,rocketmq會主動輪訓自己儲存的prepare的訊息,超過一定時間的資料會**對應主動方的**介面詢問情況]或者rabbitmq),保證訊息傳送和主動方事務在同一事務中,保證主動方成功訊息傳送成功主動方失敗訊息失敗

2)接著就是被動方消費訊息,直至到成功為止(注意消費需要保證冪等),如果消費放多次都不成功,那麼就想辦法通知主動方進行回滾或者人工來回滾和補償

----------------------------------

saga模式和tcc區別

簡單點saga就是比tcc少了try:

saga的核心就是補償,一階段就是服務的正常順序呼叫(資料庫事務正常提交),如果都執行成功,則第二階段則什麼都不做;但如果其中有執行發生異常,則依次呼叫其補償服務來保證最終的一致性。

tcc的特點在於業務資源檢查與加鎖,一階段進行校驗,資源鎖定,如果第一階段都成功,二階段對鎖定資源進行交易邏輯,否則,對鎖定資源進行釋放。

---------------------------------

seata原理(at模式)(跟xa不一樣的是第一階段就提交,第二階段是進行是否回滾的確認):

實際就是第一階段先提交並保留需要回滾的資訊,然後第二段就確認是否要回滾,他主要特點是可以解析sql提交前的資料資訊後續用於回滾

流程如下:

第一階段:

1.解析sql語句,得到 sql 的型別(update),表(product),條件(where name = 'abc')等相關的資訊。

2.查詢老資料,根據上面的where語句sql,去資料庫查詢原始的資料。

如 select * from product where name = 'abc';得到原始的資料,如該行id=1,然後記錄下來。

3.執行第一步的sql語句,即執行update,修改資料庫的該記錄的值。(預設是隔離級別是讀未提交)

4.查詢修改後的值,select * from product where id =1.得到該行值,記錄下來。

5.插入回滾日誌,將老值、新值以及sql語句組成乙個將來可用於回滾的日誌,插入到undo_log表

6.向tc server註冊分支,申請product表,id=1的行的全域性鎖。注意,這個全域性鎖是相對於所有可能的同時在執行的分布式事務而言的。一旦某個分支,獲取了該記錄的全域性鎖,在解鎖之前,任何其他的分布式事務,不能修改該資料。

7.本地事務提交,將自己的本地事務、和前面的undo log一起提交。

8.將本地事務提交的結果上報給tc server。如成功、失敗

第二階段:

成功的情況:分支收到了tc下發的成功請求,立馬返回我已ok的結果給tc,然後非同步執行刪除undo log的操作。因為成功了,所以用來回滾的undo log就沒意義了,非同步刪除掉就好。

失敗的情況:

1.分支收到了tc下發的失敗請求,開始執行回滾邏輯。

2.通過 xid 和 branch id 查詢到相應的 undo log 記錄。

3.資料校驗:拿 undo log 中的後鏡與當前資料進行比較,如果有不同,說明資料被當前全域性事務之外的動作做了修改。

4.根據 undo log 中的前映象和業務 sql 的相關資訊生成並執行回滾的語句。

update product set name = 'abc' where id = 1;

5.提交本地事務。並把本地事務的執行結果(即分支事務回滾的結果)上報給 tc 

---------------------------------

ps:

1.分布式事務不應該太多~應該盡量通過監控錯誤日誌資訊的方式 通知快速修復資料等,大量的分布式事務會增加系統的複雜性降低吞吐量~90%的都不應該用分布式事務解決

2.一般扣庫存,訂單那些採用可靠訊息最終一致性性方案,跟金錢有關需要嚴格保證的採用tcc,但是像發簡訊,積分等等不太重要的業務不要使用分布式事務解決,通過事前監控時候快速通知解決來搞定

參考:

分布式事務Seata最簡單的安裝方案

seata安裝方案,不需要nacos。server端儲存模式使用mysql 註冊中心使用file 直接解壓,進入conf目錄修改file.conf和register.conf file.conf指定儲存模式為資料庫,並配置資料庫相關資訊 register.conf 指定註冊中心為file 建立資料庫...

分布式事務(二)分布式事務方案

首先這是普通事務 下面是分布式事務 在微服務系統中,每個微服務應用都可能會有自己的資料庫,它們首先需要控制自己的本地事務。一項業務操作可能會呼叫執行多個微服務。如何保證多個服務執行的多個資料庫的操作整體成功或整體失敗?這就是分布式事務要解決的問題。cap 和 base 是對大規模網際網路系統分布式實...

分布式事務 分布式事務的實現

如果在多個服務中需要對不同的資料庫進行操作。因為不同服務操作的資料庫都不同,所以保證在同乙個事務中完成操作顯然是不科學的。那實現分布式事務的思想 1 方法入口,建立一條日誌記錄,狀態定義為初始狀態,即儲存本條日誌記錄 可以儲存在資料庫中,也可以寫出到本地磁碟檔案 2 可以在非同步執行緒或在定時任務中...