分散式事務:XA和Seata的XA模式

来源:https://www.cnblogs.com/jingdongkeji/archive/2023/10/08/17748219.html
-Advertisement-
Play Games

上一篇內容《從2PC和容錯共識演算法討論zookeeper中的Create請求》介紹了保證分散式事務提交的兩階段提交協議,而XA是針對兩階段提交提出的介面實現標準,本文則對XA進行介紹 ...


上一篇內容《從2PC和容錯共識演算法討論zookeeper中的Create請求》介紹了保證分散式事務提交的兩階段提交協議,而XA是針對兩階段提交提出的介面實現標準,本文則對XA進行介紹。

1. XA

XA (eXtended Architecture 擴展架構)X/Open組織提出的跨異構技術實現兩階段提交的介面標準。

分散式事務包含兩種類型:資料庫內部的分散式事務,在這種情況下,所有參與事務的節點都運行相同的資料庫軟體;異構分散式事務,參與者由兩種或兩種以上的不同資料庫軟體組成。

它於 1991 年推出並得到了廣泛的實現:許多傳統關係資料庫包括 PostgreSQL、MySQL、DB2、SQL Server 和 Oracle;消息代理包括 ActiveMQ、HornetQ、MSMQ 和 IBM MQ都支持 XA。它不是一個網路協議而是定義了事務管理器(Transaction Manager)、應用程式(Application Program)資源管理器(Resource Manager)之間交互的CAPI(Common Application Programming Interface)介面標準,如下圖所示,但是標準中並沒有指明該如何實現,例如在Java EE中,XA使用的是Java事務API(JTA, Java Transaction API)實現的。

CAPI: 國際標準的通用應用交互介面。

image.png

其中三個組件的職責如下:

應用程式(Application Program):負責定義事務的開啟、提交或中止,並能夠訪問事務內的資源(資料庫等)

資源管理器(Resource Manager):負責對資源進行管理,相當於兩階段提交中的參與者,能夠與事務管理器通過介面交互來傳遞必要的事務信息

事務管理器(Transaction Manager):負責管理全局事務,分配事務ID,監控事務的執行進度,並負責事務的開啟、提交和回滾等,相當於兩階段提交中的協調者

XA同樣也分為準備階段提交階段,它對分散式事務管理的流程如下

  • 準備階段:AP與TM交互,開啟一個全局分散式事務,併發送請求到每個RM,執行數據變更邏輯,此時每個RM會向TM發送請求註冊分支事務,在執行完業務邏輯後報告準備提交的狀態(事務執行完未提交),之後AP會根據RM的響應在提交階段做出反饋

  • 提交階段:如果所有的RM都回覆“是”,表示它們已經準備好提交,那麼AP會在該階段向TM發出提交請求,分散式事務提交;否則,AP會向TM發出中止請求,分散式事務回滾

2. Seata的XA的模式

Seata中有三個角色事務管理器(Transaction Manager)資源管理器(Resource Manager)事務協調者(Transaction Coordinator)。在XA模式下,利用事務資源(資料庫、消息服務等)對XA協議的支持,來對分散式事務進行管理。

但是,在Seata中三個角色的定義與XA協議標準中角色的定義有所區別:事務管理器(Transaction Manager)應該對應XA協議中的應用程式(Application Program);事務協調者(Transaction Coordinator)對應XA協議中的事務管理器(Transaction Manager)。我認為它們只是在命名上的區別,為了上下文各名詞的統一,避免發生因名詞不一致而理解混淆的問題,決定以XA標準協議中的定義進行講解,特此強調

下圖是Seata管理分散式事務的流程圖,與第一小節中所述事務流程相同,不再贅述。

image.png

2.1 XA模式實戰分析

有了理論基礎,我們以商城系統為例進行簡單地演示:訂單、商品和購物車分別為三個微服務系統,在執行下單流程時會修改商品庫存,生成訂單和刪除購物車中的商品,業務流程代碼如下,註意其中包含事務異常回滾的代碼

    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(OrderSaveParam orderSaveParam) {
        // 參數校驗等必要操作
        // ...

        // 校驗商品庫存和上架狀態
        checkGoodsStatusAndStock(goodsList, goodsCountMap);

        // 修改庫存
        reduceGoodsCount(goodsCountMap);

        // 生成訂單
        saveOrder(goodsList, goodsCountMap, orderSaveParam.getAddressId());

        // 刪除購物車中商品
        shoppingCartService.deleteShoppingCartItem(orderSaveParam.getCartItemIds(), SecurityConstants.INNER);

        // 異常回滾事務
        int i = 1 / 0;
    }



分散式事務執行的準備階段,流程圖如下

image.png

  1. Order Server 在創建訂單之前,會向 Seata Server(TM) 註冊全局事務,並分配事務ID,對應的控制台日誌如下

    2023-06-17 22:07:06.479  INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction  : Begin new global transaction [127.0.0.1:8091:36427221250506976]
    
    
    
    
  2. Order Server REST調用 Goods Server 扣減商品數量,Goods Server 在執行數據修改邏輯前會向 Seata Server 註冊分支事務,執行完業務邏輯後,並不執行事務提交

  3. Order Server REST調用 ShoppingCart Server 刪除購物車中的商品,ShoppingCart Server 在執行數據修改邏輯前會向 Seata Server 註冊分支事務,執行完業務邏輯後,同樣不執行事務提交

  4. Order Server 本地執行生成訂單和其他邏輯

接下來是分散式事務執行的提交階段,因生成訂單中代碼邏輯拋出異常,所以該分散式事務會回滾,OrderServer中對應日誌如下

2023-06-17 22:07:07.029  INFO 74703 --- [io-29009-exec-2] i.s.rm.datasource.xa.ConnectionProxyXA   : 127.0.0.1:8091:36427221250506976-36427221250506978 was rollbacked
2023-06-17 22:07:07.220  INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction  : Suspending current transaction, xid = 127.0.0.1:8091:36427221250506976
2023-06-17 22:07:07.220  INFO 74703 --- [io-29009-exec-2] i.seata.tm.api.DefaultGlobalTransaction  : [127.0.0.1:8091:36427221250506976] rollback status: Rollbacked



image.png

  1. Order Server 向 Seata Server 發送中止請求,隨後 Seata Server 向 Goods Server 和 ShoppingCart Server 發送事務回滾請求

  2. Goods Server 和 ShoppingCart Server 收到事務回滾請求後,將各自註冊的分支事務回滾,最終全局分散式事務回滾,以保證數據的一致性。Goods Server 分支事務回滾對應的日誌如下,可以發現分支事務的ID為全局事務ID-分支ID,並顯示PhaseTwo_Rollbacked 在階段二回滾

2023-06-17 22:07:07.081  INFO 74680 --- [h_RMROLE_1_4_24] i.s.c.r.p.c.RmBranchRollbackProcessor    : rm handle branch rollback process:xid=127.0.0.1:8091:36427221250506976,branchId=36427221250506986,branchType=XA,resourceId=jdbc:mysql://127.0.0.1:3306/fy_mall_goods,applicationData=null
2023-06-17 22:07:07.081  INFO 74680 --- [h_RMROLE_1_4_24] io.seata.rm.AbstractRMHandler            : Branch Rollbacking: 127.0.0.1:8091:36427221250506976 36427221250506986 jdbc:mysql://127.0.0.1:3306/fy_mall_goods
2023-06-17 22:07:07.096  INFO 74680 --- [h_RMROLE_1_4_24] i.s.rm.datasource.xa.ResourceManagerXA   : 127.0.0.1:8091:36427221250506976-36427221250506986 was rollbacked
2023-06-17 22:07:07.096  INFO 74680 --- [h_RMROLE_1_4_24] io.seata.rm.AbstractRMHandler            : Branch Rollbacked result: PhaseTwo_Rollbacked



註:如果有朋友想試試Seata的XA模式,可以參考示例代碼倉庫FangYuan33/book-spring-cloud,對應的方法入口為/saveOrder

3. 對XA的思考

XA能夠保持多個參與者數據相互一致,但是同時也引入了比較嚴重的運維問題

因為如果協調者宕機,那麼其中已經準備但未提交事務的所有參與者都會被阻塞。被阻塞的根本是,例如在讀已提交隔離級別上,資料庫事務通常會獲取到待修改行數據的行級排他鎖來防止臟寫。在分散式事務提交或中止前,參與者資料庫不能釋放這些鎖,因此協調者宕機多久,這些鎖就要持有多久(在沒有認為干預的情況下)。這些鎖被持有的期間,導致其他事務不能修改這些數據(根據資料庫的不同,讀取操作也可能被阻塞),所以這些數據相關的業務都會被阻塞,導致應用大面積的不可用,直至存疑事務被解決(提交/中止)。

理論上,如果協調者崩潰並重新啟動,它應該從日誌中恢復事務的狀態,並解決現存的疑慮事務,但是在實際生產中,仍然會有疑慮事務的出現(可能是事務日誌被破壞)。也許你可能會考慮將相關應用的資料庫伺服器重啟,但是在2PC正確的實現中,為了原子性的保證,重啟後也必須持有存疑事務的鎖。那麼這樣唯一的解決方案是讓管理員手動提交還是回滾事務,這是引入運維問題的所在。不過,許多XA事務的實現都有一個叫做啟髮式決策的逃生出口,允許參與者單方面決定提交或放棄一個存疑事務,而無需等待協調者的決定,但是這也正是避免災難性情況的手段,而不是為了日常的使用,因為這種方式有可能會破壞事務的原子性。

所以,協調者的高可用是需要我們考慮的問題,它本身也是一種資料庫(保存了事務的結果),需要像其他應用資料庫服務一樣被認真的對待。


巨人的肩膀

作者:京東物流 王奕龍

來源:京東雲開發者社區 自猿其說Tech 轉載請註明來源


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:背景 1. 講故事 中秋國慶長假結束,哈哈,在老家拍了很多的短視頻,有興趣的可以上B站觀看:https://space.bilibili.com/409524162 ,今天繼續給大家分享各種奇奇怪怪的.NET生產事故,希望能幫助大家在未來的編程之路上少踩坑。 話不多說,這篇看一個.NET程式集泄 ...
  • 前言 上傳大文件時,原始HTTP文件上傳功能可能會影響使用體驗,此時使用分片上傳功能可以有效避免原始上傳的弊端。由於分片上傳不是HTTP標準的一部分,所以只能自行開發相互配合的服務端和客戶端。文件分片上傳在許多情況時都擁有很多好處,除非已知需要上傳的文件一定非常小。分片上傳可以對上傳的文件進行快速分 ...
  • Debian,作為最受歡迎的 Linux 發行版之一,於 2023 年 6 月 10 日正式發佈了其最新版本 Debian 12,代號“Bookworm”。Debian 12 帶來了許多新特性和改進,其中最引人註目的是 Linux 內核的升級,從之前的 5.10 LTS 升級到了 6.1。 這兩天嘗 ...
  • Css實現瀏覽滾動條效果 前言 也是有大半個月沒有更新文章了,大部分時間都在玩,然後就是入職的事。今天就更新一個小知識,刷抖音的時候看到的,感覺還不錯。 屬性介紹 關鍵屬性animation-timeline:動畫名稱; 用於控制動畫的時間軸。它可以讓你在一個元素上同時播放多個動畫,控制它們的開始時 ...
  • 一、簡介 ssh(secure shell,安全外殼協議),該協議有2個常用的作用:遠程連接、遠程文件傳輸。 協議使用埠號:預設是22。 可以是被修改的,如果需要修改,則需要修改ssh服務的配置文件: #/etc/ssh/ssh_config 埠號可以修改,但是得註意2個事項: a. 註意範圍, ...
  • 為什麼要使用skb_reserve函數把邊界對齊 skb_reserve 函數通常用於網路編程中的數據包處理,特別是在構建自定義協議棧或數據包處理模塊時。它的作用是為數據包的頭部預留額外的空間,以確保數據包的頭部數據在記憶體中是對齊的。 邊界對齊的概念是因為許多硬體平臺和網路協議要求數據包頭的位元組對齊 ...
  • 前言 每個索引都是一顆B+樹,對於聚簇索引,每一條完整記錄都存儲在B+樹都葉子節點上;對於其他索引,葉子節點存儲了索引列和主鍵。這麼做都是為了提升查詢速度,那麼在實際使用中,是不是應該給所有列都添加索引呢,索引該如何使用呢? 先見一張表,隨機添加一些數據: CREATE TABLE single_t ...
  • 一、遇到問題 今天在做添加數據的時候,發現手機號存儲錯誤,報錯信息是: Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column 'f_phone' ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...