天天看點

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

作者:JAVA後端架構
深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

什麼是事務

開始前,先來問大家兩個問題:

第一問題:什麼是事務?

在編寫代碼的時候,我們常常會遇到各種事務問題。那麼,我們該如何清晰明了地描述事務的概念呢?事務是指如何確定對一組(多個)資料操作在執行的過程中,要麼全部都能夠成功執行,要麼全部失敗。而且,一旦事務成功執行,所變更的資料不會丢失;若事務失敗,所有的資料變更都要回到事務開始之前的狀态。簡單來說,事務包括多個操作,這些操作要麼全部執行,要麼全部不執行。

第一問題:保證事務的目的是什麼?

在了解事務的概念後,我們需要明确實作事務的最終目的是什麼?如果在一組事務中,有些操作執行了,有些沒執行,會産生什麼問題呢?舉個例子,如果你給父母轉賬1W元,結果你的賬戶扣了1W元,但是你父母的賬戶卻沒有加上1W元,這時你就會開始懷疑自己賺錢的意義。這種情況就是所謂的“資料一緻性問題”。

當大家明确了以上兩個問題之後,我才能繼續往下跟大家繼續分享今天的這個主題,因為今天這個主題,都是在圍繞着怎麼保證事務一緻性的問題展開的。

單程序下完美的解決方案

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

A(原子性)、C(一緻性)、I(隔離性)、D(持久性)。C 是事務最終的目标,那麼A、I、D 就是為實作這個目标努力的打工仔,如果這幾個打工仔不能正常工作的話,那麼一緻性就得不到保障。

原子性:原子性是指一組操作要麼全部執行成功,要麼全部執行失敗。這個概念和事務十分相似。如果不保證原子性,就可能出現在同一個事務中,某些操作執行成功,而另一些操作執行失敗的情況,這會導緻資料不一緻,而且很難恢複。是以,原子性是保障資料一緻性的重要特性之一。

隔離性: 事務的隔離性指的是多個事務之間的操作不會互相影響,它們之間互相隔離。如果沒有隔離性,就好像兩個人在同一張畫布上畫畫,一個畫豬,一個畫狗,最後會畫出一個四不像。也就是說,如果不保證隔離性,一個人修改資料時,其他人也可以修改,這會導緻資料不一緻。

持久性:持久性指的是一旦事務送出,所産生的資料變更不會因為任何意外(比如資料庫故障或伺服器當機)而丢失。因為如果事務産生的部分資料丢失,就會導緻資料不一緻。

單機事務實作采用ACID模型,通過加鎖實作對需要操作相同資料的事務進行隔離,保證事務之間的操作不會互相影響,進而實作了隔離性。在事務送出之前,記錄資料修改前的日志(undo log)和事務需要變更資料的日志(redo log),以保證事務不論在哪個階段都能通過undo log對事務資料進行復原,把資料恢複到事務開始之前的狀态。同時,通過redo log保證事務在送出後,即使資料庫或伺服器出現故障,也能重做未成功寫入磁盤的資料,實作了事務的持久性和原子性。

分布式事務的誕生

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

在公司發展初期,由于使用者量少、資料量少,系統的并發請求并不高,是以隻需要将應用單點部署即可滿足業務需求。但随着業務的快速發展和複雜度的增加,幾乎每個公司的系統都會從單體架構轉向分布式架構,特别是微服務架構。

單程序事務演變成多程序事務時,場景發生了改變。之前是一個人獨立完成一項任務,現在變成了多個人協作完成同一項任務。在單程序事務中,決定權在自己手中,是以決定復原或送出事務較為容易。但在多程序事務中,如何協調多個人的操作以達到一緻性,則成為一個難題。是以,需要有一個統一的協調者來協調多個節點的操作,以確定多個程序操作的一緻性。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

比如從圖中看到,假設在RPC調用過程中,其中有一個RPC調用異常了,我們怎麼去復原前面兩個已經執行成功的事務呢?

這就不得不涉及到我們應該怎麼去設計一個分布式事務的執行模型。

分布式事務模型2PC

目前絕大部分分布式事務架構為 2PC 二階段事務模型。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

2PC協定的核心思路是協調者和參與者通過兩個階段的協商達成最終操作的一緻性。首先,第一階段的目的是确認各個參與者是否具備執行事務的條件。根據第一階段參與者的響應結果,制定出第二階段的事務政策。如果第一階段中任意一個參與者不具備事務執行條件,那麼第二階段的決策就是復原事務。隻有在所有參與者都具備事務執行條件的情況下,才進行整體事務的送出。

但是這個模型也不是萬能的,在遇到異常情況,很可能就會造成資料不一緻(但是這個不一緻,在最後都會有架構驅動達成最終一緻性)

我下面舉兩個例子

參與者挂掉

如果在第一階段,協調者發送Prepare指令給所有的參與者後,參與者挂掉了,那麼此時協調者因為遲遲收不到參與者的消息而導緻逾時,是以協調者在逾時之後會統一發送abort指令進行事務復原。

如果在第二階段,協調者發送commit或者abort指令給所有參與者後,參與者挂掉了,那麼協調者會在逾時之後進行消息重發,直到參與者恢複後收到到commit或者abort ,向協調者傳回成功。

協調者挂掉

協調者在第一階段發送Prepare指令後挂掉,那麼此時參與者此時會一直得不到協調者下一步的指令,那麼此時參與者會一直陷入阻塞狀态,資源也會一直被鎖住,直到協調者恢複之後向參與者發出下一步的指令。

協調者在第二階段挂掉,那麼此時協調者已向所有者發出最後階段的指令了,是以收到指令的參與者會完成最後的commit或rollback操作,對于參與者來說事務已經結束,是以不存在阻塞和鎖的問題, 當協調者恢複後,會把事務日志狀态标記為結束。

CAP定律

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

強一緻性的事務一緻性方案在單機事務場景下可以完美實作,但在分布式事務場景下效果并不理想。這是因為單機事務和分布式事務所面臨的場景不同。在單機事務中,隻需要考慮資料一緻性問題。而在分布式事務場景中,需要同時考慮資料一緻性、多節點的可用性、網絡分區等多個問題。是以,強一緻性的事務模型始終無法完美解決分布式事務場景。

由此引出CAP定律,什麼是CAP定律呢?

CA組合就是保證一緻性和可用性,放棄分區容忍性,即不進行分區,不考慮由于網絡不通或節點挂掉的問題。那麼系統将不是一個标準的分布式系統,我們最常用的關系型資料庫就滿足了CA。

CP組合就是保證一緻性和分區容忍性,放棄可用性。Zookerper就是追求強一緻性,放棄了可用性,還有跨行轉賬,一次轉賬請求要等待雙方銀行系統都完成整個事務才能完成。

AP組合就是保證可用性和分區容忍性,放棄一緻性。這是分布式系統設計時的選擇。

BASE理論

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

CAP理論表明在分布式系統中,無法同時滿足一緻性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)。在分布式系統中,分區容錯性是必須滿足的,而可用性是分布式系統設計的主要目标,通常需要犧牲一緻性來保證可用性和分區容錯性。

但是,犧牲一緻性并不意味着完全放棄它。所謂犧牲,是指在一段時間内,系統可以暫時不保證一緻性,但最終還是要恢複到一緻性狀态,通常被稱為最終一緻性。基于最終一緻性模型,BASE理論提出了一套實踐理論,從基本可用性、軟狀态和最終一緻性三個方面來指導我們進行分布式系統設計。

Seata模型介紹

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

Seata(Simple Extensible Autonomous Transaction Architecture,簡單可擴充自治事務架構)是 2019 年 1 月份阿裡巴巴和螞蟻集團共同開源的分布式事務解決方案。目前在GitHub已經有超過 2 萬+ star,社群非常活躍。我在19年7月份的時候正式加入Seata開源社群。

在整個 Seata 體系下,所有模式(AT、TCC、XA、SAGA)都遵循這套角色模型。

Seata AT 模式

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

從圖中以及代碼中可以看到,在分布式事務場景下,隻需要在發起方的方法上面添加注解@GlobalTransaction注解就可以了,完全不「幹擾」業務的邏輯。

Seata AT 模式:通信互動

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

可以看出,AT 模式遵循 TC、TM、RM 互動:

  1. 首先TM回向TC服務發送一個Begin指令開啟全局事務,TC 傳回全局事務xid;
  2. 各個分支事務向TC服務發送Branch Register進行分支事務注冊;
  3. TM 向TC服務決議全局送出或者復原,TC 收到TM最終的二階段指令後,會驅動各個分支進行送出或者復原。

可以看出,Seata AT模式是一個 2PC 事務模型。

Seata AT 模式如何保證對業務的無入侵?

1、資料源代理

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

Seata 在資料源做了一層代理層,是以我們使用 Seata 時,我們使用的資料源實際上用的是 Seata 自帶的資料源代理 DataSourceProxy,Seata 在這層代理中加入了很多邏輯,主要是解析 SQL,把業務資料在更新前後的資料鏡像組織成復原日志,并将 undo log 日志插入 undo_log 表中,保證每條更新資料的業務 sql 都有對應的復原日志存在。

2、一階段

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

可以看出,AT模式的分支事務,必須使用支援ACID的關系型資料且業務與復原日志需要在同一個資料庫中,因為業務SQL和復原日志,需要使用本地事務同時插入資料庫中,要麼同時成功要麼同時失敗。如果分開在不同資料庫中,就又會産生分布式事務問題,這純屬于套娃行為了。

3、二階段送出

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

當TM決議全局事務送出,TC會發送commit指令給各個分支事務,因為“業務 SQL”在一階段已經送出至資料庫, 是以 Seata 架構隻需将一階段儲存的快照資料和行鎖删掉,完成資料清理即可。

4、二階段復原

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

當TM決議全局事務復原,TC會發送rollback指令給各個分支事務,復原方式便是用“before image”還原業務資料;但在還原前要首先要校驗髒寫,對比“資料庫目前業務資料”和 “after image”,如果兩份資料完全一緻就說明沒有髒寫,可以還原業務資料,如果不一緻就說明有髒寫,出現髒寫就需要轉人工處理。

從整個流程可以看出來,在沒有發生髒寫的情況下,所有的事務操作都被Seata資料源代理悄悄地處理了。

Seata AT 模式:事務隔離級别

剛剛我們說到髒寫,那麼Seata AT模式是怎麼發生髒寫或者髒讀的呢?這不得不從Seata的預設的事務隔離級别說起。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

想象一個場景:

某個全局事務事務下有若幹個分支事務,在全局事務執行過程中(全局事務還沒執行完),某個本地事務送出了,如果Seata沒有采取任何措施,會造成什麼問題?

傳統意義的髒讀是讀到了未送出的資料,Seata 髒讀是讀到了全局事務下未送出的資料,全局事務可能包含多個本地事務,某個本地事務送出了不代表全局事務送出了。

在絕大部分應用在讀已送出的隔離級别下工作是沒有問題的,而實際上,這當中又有絕大多數的應用場景,實際上工作在讀未送出的隔離級别下同樣沒有問題。

在極端場景下,應用如果需要達到全局的讀已送出,Seata 設計了由事務協調器維護的全局寫排他鎖,來保證事務間的寫隔離,同時,将全局事務預設定義在讀未送出的隔離級别上。

但是預設情況下,Seata 的全局事務是工作在讀未送出隔離級别的,保證絕大多數場景的高效性。

Seata AT 模式:寫隔離

1、送出成功

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

兩個全局事務 tx1 和 tx2,分别對 a 表的 m 字段進行更新操作,m 的初始值 1000。

tx1 先開始,開啟本地事務,拿到本地鎖,更新操作 m = 1000 - 100 = 900。本地事務送出前,先拿到該記錄的 全局鎖 ,本地送出釋放本地鎖。tx2 後開始,開啟本地事務,拿到本地鎖,更新操作 m = 900 - 100 = 800。本地事務送出前,嘗試拿該記錄的 全局鎖 ,tx1 全局送出前,該記錄的全局鎖被 tx1 持有,tx2 需要重試等待 全局鎖 。

tx1 二階段全局送出,釋放 全局鎖 。tx2 拿到 全局鎖 送出本地事務。

2、事務復原

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

如果 tx1 的二階段全局復原,則 tx1 需要重新擷取該資料的本地鎖,進行反向補償的更新操作,實作分支的復原。

此時,如果 tx2 仍在等待該資料的 全局鎖,同時持有本地鎖,則 tx1 的分支復原會失敗。分支的復原會一直重試,直到 tx2 的 全局鎖 等鎖逾時,放棄 全局鎖 并復原本地事務釋放本地鎖,tx1 的分支復原最終成功。

因為整個過程 全局鎖 在 tx1 結束前一直是被 tx1 持有的,是以不會發生 髒寫 的問題。

Seata AT 模式:讀隔離

Seata AT模式下的髒讀是指在全局事務未送出之前,其他業務可能會讀取已送出的分支事務的資料。本質上,這意味着Seata預設的全局事務是讀未送出。

在特定場景下,可能需要全局讀取已送出資料。目前,Seata将通過代理SELECT FOR UPDATE語句來實作此需求。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

執行SELECT FOR UPDATE語句将申請全局鎖。如果全局鎖已被其他事務持有,則Seata将釋放本地鎖并復原SELECT FOR UPDATE語句的本地執行,并進行重試。在此過程中,查詢将被阻塞,直到全局鎖被擷取,并確定讀取的資料是已送出的,然後才會傳回查詢結果。

Seata AT 模式:與XA的差別

seata 的事務送出方式跟 XA 協定的兩段式送出在總體上來說基本是一緻的,那它們之間有什麼不同呢?

我們都知道 XA 協定它依賴的是資料庫層面來保障事務的一緻性,也即是說 XA 的各個分支事務是在資料庫層面上驅動的,由于 XA 的各個分支事務需要有 XA 的驅動程式,一方面會導緻資料庫與 XA 驅動耦合,另一方面它會導緻各個分支的事務資源鎖定周期長,這也是它沒有在網際網路公司流行的重要因素。

前面在将為什麼無侵入的時候講到,Seata 在資料源做了一層代理層,是以我們使用 Seata 時,我們使用的資料源實際上用的是 Seata 自帶的資料源代理 DataSourceProxy。

這樣做的好處就是,本地事務執行完可以立即釋放本地事務鎖定的資源,然後向 TC 上報分支狀态。

當 TM 決議全局送出時,就不需要同步協調處理了,TC 會異步排程各個 RM 分支事務删除對應的 undo log 日志即可,這個步驟非常快速地可以完成,XA就做不到,它必須同步等待所有分支處理完之後才認為全局事務已完成,這個期間被鎖定的資源其它業務是不能通路的,這也就是為什麼XA性能這麼差的原因。正常的業務來說,二階段commit的幾率遠大于rollback,是以Seata AT模式相對于XA性能提升是非常巨大的。

當 TM 決議全局復原時,RM 收到 TC 發送的復原請求,RM 通過 XID 找到對應的 undo log 復原日志,然後執行復原日志完成復原操作。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

如上圖所示,Seata 的 RM 實際上是已中間件的形式放在應用層,不用依賴資料庫對協定的支援,完全剝離了分布式事務方案對資料庫在協定支援上的要求。

TCC 模式

TCC是分布式事務的一種解決方案,它也是一種2PC模型。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

TCC優點:

1、性能高:沒有全局鎖,本地事務鎖在本地操作完成後馬上會釋放,不會像2PC、3PC 一樣整個事務執行的過程都會鎖住資源,是以TCC性能非常高。

2、具備隔離性: 通過隔離資源達到事務隔離的目的,先預留資源,再真正使用資源,避免了出現兩個事務并發時可能導緻的同一個資源被使用多次的問題,适合資源敏感的場景。

3、允許事務失敗:可以進行事務復原。

TCC缺點:

1、業務侵入性強:需要修改原來的結構設計來預留資源, 需要在原有的方法基礎上把業務拆分為Try、Confirm、Cancel三個方法。

TCC适用場景:

有資源隔離性要求、并且對業務系統有控制權,有修改結構的權限。

Seata TCC 模式:使用效果

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

如圖所示,參與者需要實作Try、Confirm、Cancel這三個方法,并在Try方法中添加@TwoPhaseBusinessAction注解,填寫二階段commit和rollback的方式到注解參數中。随後,使用Dubbo等rpc協定釋出遠端RPC服務,在發起方的方法中添加@GlobalTransactional注解來開啟全局事務,然後在全局事務内調用參與者的一階段Try方法。此時,二階段就由Seata架構來驅動完成。

Seata TCC 模式:通信互動

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

結合剛剛的使用例子,我們來看看 Seata 是如何實作TCC模式的,在這張通信互動圖可以看出,它與AT模式一樣遵循 TC、TM、RM 角色模型。

其中TM負責開啟全局事務,參與者執行try方法時會注冊分支事務,TM決議全局事務送出或復原後,TC協調者會驅動全局事務内的參與者進行送出或者復原。

Seata TCC 模式:實踐例子

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

如圖所示,Try 方法作為一階段準備方法,需要做資源的檢查和預留。在扣錢場景下,Try 要做的事情是就是檢查賬戶餘額是否充足,預留轉賬資金,預留的方式就是當機 A 賬戶的 轉賬資金。Try 方法執行之後,賬号 A 餘額雖然還是 100,但是其中 30 元已經被當機了,不能被其他事務使用。

二階段 Confirm 方法執行真正的扣錢操作。Confirm 會使用 Try 階段當機的資金,執行賬号扣款。Confirm 方法執行之後,賬号 A 在一階段中當機的 30 元已經被扣除,賬号 A 餘額變成 70 元 。

如果二階段是復原的話,就需要在 Cancel 方法内釋放一階段 Try 當機的 30 元,使賬号 A 的回到初始狀态,100 元全部可用。

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

TCC可能會遇到什麼樣的問題?

即使我們擁有了一套完備的TCC接口,也不能高枕無憂。在微服務架構下,很可能會遇到網絡逾時、重發、機器當機等一系列異常情況,這會導緻分布式事務執行出現異常。根據螞蟻多年的實踐,我們發現最常見的異常有三種,分别是空復原、幂等、懸挂。

是以,TCC接口需要解決這三類問題。實際上,Seata架構已經支援這三種異常的處理,我們将把這些異常的處理移植到Seata架構中。這樣,業務就無需關注這些異常情況,可以專注于業務邏輯。

雖然業務無需關注這些異常,但了解其内部實作機制有助于更好地排查問題。接下來,我将為大家一一講解這三類異常出現的原因以及對應的解決方案。

Seata TCC 模式:如何防止空復原?

什麼是空復原?

TCC 服務在未收到 Try 請求的情況下收到 Cancel 請求,這種場景被稱為空復原;空復原在生産環境經常出現,使用者在實作TCC服務時,應允許允許空復原的執行,即收到空復原時傳回成功。

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

如圖所示,事務協調器在調用 TCC 服務的一階段 Try 操作時,可能會出現因為丢包而導緻的網絡逾時,此時事務管理器會觸發二階段復原,調用 TCC 服務的 Cancel 操作,而 Cancel 操作調用未出現逾時。

要想防止空復原,那麼必須在 Cancel 方法中識别這是一個空復原,Seata 是如何做的呢?

Seata 的做法是新增一個 TCC 事務控制表,包含事務的 XID 和 BranchID 資訊,在 Try 方法執行時插入一條記錄,表示一階段執行了,執行 Cancel 方法時讀取這條記錄,如果記錄不存在,說明 Try 方法沒有執行。

Seata TCC 模式:如何防懸挂?

懸挂指的是二階段 Cancel 方法比 一階段 Try 方法優先執行,由于允許空復原的原因,在執行完二階段 Cancel 方法之後直接空復原傳回成功,此時全局事務已結束,但是由于 Try 方法随後執行,這就會造成一階段 Try 方法預留的資源永遠無法送出和釋放了。

那麼懸挂是如何産生的呢?

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

在圖示中,當事務協調器調用TCC服務的一階段Try操作時,由于網絡擁堵等原因,可能會出現逾時的情況。此時,事務管理器會觸發二階段復原,調用TCC服務的Cancel操作,但Cancel調用未逾時。之後,被網絡擁堵延遲的一階段Try資料包被TCC服務收到,導緻二階段Cancel請求比一階段Try請求先執行,這會導緻TCC服務在執行晚到的Try之後,永遠不會再收到二階段的Confirm或Cancel請求,進而導緻TCC服務懸挂的情況。

使用者在實作 TCC 服務時,要允許空復原,但是要拒絕執行空復原之後 Try 請求,要避免出現懸挂。

Seata 是怎麼處理懸挂的呢?

在 TCC 事務控制表記錄狀态的字段 status 中增加一個狀态:

  1. suspended:4

當執行二階段 Cancel 方法時,如果發現 TCC 事務控制表有相關記錄,說明二階段 Cancel 方法優先一階段 Try 方法執行,是以插入一條 status=4 狀态的記錄,當一階段 Try 方法後面執行時,判斷 status=4 ,則說明有二階段 Cancel 已執行,并傳回 false 以阻止一階段 Try 方法執行成功。

Seata TCC 模式:如何幂等控制?

幂等問題指的是 TC 重複進行二階段送出,是以 Confirm/Cancel 接口需要支援幂等處理,即不會産生資源重複送出或者重複釋放。

那麼幂等問題是如何産生的呢?

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

參與者執行完二階段之後,由于網絡抖動或者當機問題,會造成 TC 收不到參與者執行二階段的傳回結果,TC 會重複發起調用,直到二階段執行結果成功。

Seata 是如何處理幂等問題的呢?

同樣的也是在 TCC 事務控制表中增加一個記錄狀态的字段 status,該字段有有 3 個值,分别為:

  1. tried:1
  2. committed:2
  3. rollbacked:3

二階段 Confirm/Cancel 方法執行後,将狀态改為 committed 或 rollbacked 狀态。當重複調用二階段 Confirm/Cancel 方法時,判斷事務狀态即可解決幂等問題。

最後

時間和篇幅的限制,隻講了AT模式和TCC模式,而XA和SAGA模式還沒有講到。畢竟分布式事務是一個非常廣泛的領域,我也在不斷學習中,希望能夠在後續分享中給大家帶來更多的内容。

為幫助開發者們提升面試技能、有機會入職BATJ等大廠公司,特别制作了這個專輯——這一次整體放出。

大緻内容包括了: Java 集合、JVM、多線程、并發程式設計、設計模式、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat等大廠面試題等、等技術棧!

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

歡迎大家關注公衆号【咕泡Java】,回複【007】,擷取以上最新Java後端架構VIP學習資料以及視訊學習教程,然後一起學習,一文在手,面試我有。

每一個專欄都是大家非常關心,和非常有價值的話題,如果我的文章對你有所幫助,還請幫忙點贊、好評、轉發一下,你的支援會激勵我輸出更高品質的文章,非常感謝!

深入淺出剖析分布式事務,輕松掌握實作原理與應用技巧!

繼續閱讀