問題:
有一個請求去調用了服務A,A中需要向數據庫寫入數據,其中A里面又調用了服務B,B中也向服務器寫入了一些數據,當A成功調用B之后,B正常執行了,A的操作發生了異常,A操作的數據可以正常回滾,那么問題是B服務的事務如何與A保持一致呢?
解決方案:
服務A與服務B屬於不同的應用,通過dubbo遠程調用,要做到二者寫庫操作一同提交/一同回滾,服務A和服務B必須參與同一個跨應用的全局事務,並保證二者對應的DB事務必須作為該全局事務的分支事務。這樣,事務管理模塊在明確了該全局事務的完成方向(commit/rollback)后,再將該全局事務下的所有分支事務逐個提交/回滾。
這是分布式事務管理的大致邏輯,其中,上述“將所有分支事務逐個提交/回滾”過程是分布式事務處理的關鍵,需要有相應故障恢復的機制,例如,當服務A的DB事務已經提交(服務B的DB事務尚未提交)時,若服務B所在節點宕機(或其使用的DB宕機)時,如何保證服務B的DB事務仍能正常提交。這個過程的實現機制有很多種,常見的有XA 2PC和TCC。
XA機制將提交過程分成prepare、commit兩個階段,事務管理模塊在prepare服務A的DB事務、服務B的DB事務都成功后,再逐個commit這些DB事務。DB在prepare返回OK后,如果沒有收到來自事務管理模塊的commit/rollback請求則會一直保留該分支事務的數據。因此,若上述宕機故障出現在prepare階段,則可以通過將prepare過的分支事務回滾,來達到全局事務回滾;若上述宕機故障出現在commit階段,后續仍然可以再次commit那些未成功commit的分支事務,最終達到全局事務提交。
TCC機制下,事務管理模塊是在服務A、服務B執行完畢后即刻提交其參與的DB事務。而后,如果全局事務決定提交,則逐個調用服務A和服務B的confirm邏輯;如果全局事務決定回滾,則逐個調用服務A和服務B的cancel邏輯(當然,confirm/cancel邏輯的執行中又會參與相應的DB事務)。若發生上述宕機故障,則只需要根據全局事務當前狀態,將服務A、服務B相應的confirm/cancel邏輯重新調用即可。因confirm/cancel邏輯可能會被多次調用,因此,需要保證其冪等性。
知名的分布式事務管理器主要有atomikos、bitronix、narayana。其中,僅atomikos支持XA和TCC兩種機制,bitronix、narayana僅支持XA機制。這三者都不提供對dubbo的開箱即用的支持,需要自行集成。
目前對dubbo提供開箱即用支持的分布式事務管理器有:ByteJTA(基於XA機制)、ByteTCC(基於TCC機制)。
一、結合MQ消息中間件實現的可靠消息最終一致性
二、TCC補償性事務解決方案
三、最大努力通知型方案
第一種方案:可靠消息最終一致性,需要業務系統結合MQ消息中間件實現,在實現過程中需要保證消息的成功發送及成功消費。即需要通過業務系統控制MQ的消息狀態
第二種方案:TCC補償性,分為三個階段TRYING-CONFIRMING-CANCELING。每個階段做不同的處理。
TRYING階段主要是對業務系統進行檢測及資源預留
CONFIRMING階段是做業務提交,通過TRYING階段執行成功后,再執行該階段。默認如果TRYING階段執行成功,CONFIRMING就一定能成功。
CANCELING階段是回對業務做回滾,在TRYING階段中,如果存在分支事務TRYING失敗,則需要調用CANCELING將已預留的資源進行釋放。
第三種方案:最大努力通知xing型,這種方案主要用在與第三方系統通訊時,比如:調用微信或支付寶支付后的支付結果通知。這種方案也是結合MQ進行實現,例如:通過MQ發送http請求,設置最大通知次數。達到通知次數后即不再通知。
具體的案例你也可以參考下龍果學院這篇博客,它上面有完整的電商系統分布式事務實現案例: 龍果社區-微服務架構的分布式事務解決方案
首先,要明確 需不需要保證數據的一致性,有些業務場景 就不需要一致性。
而你的既然需要,回滾機制,讓對方的服務提供回滾接口,調用方假設調用接口出錯,本地的東西 通過本地事物 能回滾,而外部系統 你catch了這個Exception,則要調用它的回滾接口。