1. 程式人生 > 其它 >分散式事務實戰--一個完整的xa例子

分散式事務實戰--一個完整的xa例子

事務

某些業務要求,一系列操作必須全部執行,而不能僅執行一部分。例如,一個轉賬操作:

-- 從id=1的賬戶給id=2的賬戶轉賬100元
-- 第一步:將id=1的A賬戶餘額減去100
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 第二步:將id=2的B賬戶餘額加上100
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

這兩條SQL語句必須全部執行,或者,由於某些原因,如果第一條語句成功,第二條語句失敗,就必須全部撤銷。

這種把多條語句作為一個整體進行操作的功能,被稱為資料庫事務。資料庫事務可以確保該事務範圍內的所有操作都可以全部成功或者全部失敗。如果事務失敗,那麼效果就和沒有執行這些SQL一樣,不會對資料庫資料有任何改動。

更多事務介紹

微服務

如果一個事務涉及的所有操作能夠放在一個服務內部,那麼使用各門語言裡事務相關的庫,可以輕鬆的實現多個操作作為整體的事務操作。

但是有些服務,例如生成訂單涉及做很多操作,包括庫存、優惠券、贈送、賬戶餘額等。當系統複雜程度增加時,想要把所有這些操作放到一個服務內實現,會導致耦合度太高,維護成本非常高。

針對複雜的系統,當前流行的微服務架構是非常好的解決方案,該架構能夠把複雜系統進行拆分,拆分後形成了大量微服務,獨立開發,獨立維護。

更多微服務介紹

雖然服務拆分了,但是訂單本身的邏輯需要多個操作作為一個整體,要麼全部成功,要麼全部失敗,這就帶來了新的挑戰。如何把散落在各個微服務中的本地事務,組成一個大的事務,保證他們作為一個整體,這就是分散式事務需要解決的問題。

分散式事務

分散式事務簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的伺服器上,且屬於不同的應用,分散式事務需要保證這些小操作要麼全部成功,要麼全部失敗。本質上來說,分散式事務就是為了保證不同資料庫的資料一致性。

更多分散式事務介紹

分散式事務方案包括:

  • xa
  • tcc
  • saga
  • 可靠訊息

下面我們看看最簡單的xa

XA

XA是由X/Open組織提出的分散式事務的規範,XA規範主要定義了(全域性)事務管理器(TM)和(區域性)資源管理器(RM)之間的介面。本地的資料庫如mysql在XA中扮演的是RM角色

XA一共分為兩階段:

第一階段(prepare):即所有的參與者RM準備執行事務並鎖住需要的資源。參與者ready時,向TM報告已準備就緒。

第二階段 (commit/rollback):當事務管理者(TM)確認所有參與者(RM)都ready後,向所有參與者傳送commit命令。

目前主流的資料庫基本都支援XA事務,包括mysql、oracle、sqlserver、postgre

我們看看本地資料庫是如何支援XA的:

第一階段 準備

XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'

當所有的參與者完成了prepare,就進入第二階段 提交

xa commit '4fPqCNTYeSG'

xa實踐

介紹了這麼多,我們來實踐完成一個微服務上的xa事務,加深分散式事務的理解,這裡將採用dtm作為示例

安裝go

安裝mysql

獲取dtm

git clone https://github.com/yedf/dtm.git
cd dtm

配置mysql

cp conf.sample.yml conf.yml
vi conf.yml

執行示例

go run app/main.go xa

從日誌裡,能夠找到以下輸出

# 服務1輸出
XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'

# 服務2輸出
XA start '4fPqCPijxyC'
UPDATE `user_account` SET `balance`=balance - 30,`update_time`='2021-06-09 11:50:42.493' WHERE user_id = '2'
XA end '4fPqCPijxyC'
XA prepare '4fPqCPijxyC'

# 服務1輸出
xa commit '4fPqCNTYeSG'

#服務2輸出
xa commit '4fPqCPijxyC'

整個互動的時序詳情如下

總結

至此,一個完整的xa分散式事務介紹完成。

在這篇簡短的文章裡,我們大致介紹了 事務->分散式事務->微服務處理XA事務。有興趣的同學可以通過dtm繼續研究分散式事務