日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

6 张图带你彻底搞懂分布式事务 XA 模式

發布時間:2025/3/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 6 张图带你彻底搞懂分布式事务 XA 模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | 朱晉君
來源 | 阿里巴巴云原生公眾號

XA 協議是由 X/Open 組織提出的分布式事務處理規范,主要定義了事務管理器 TM 和局部資源管理器 RM 之間的接口。目前主流的數據庫,比如 oracle、DB2 都是支持 XA 協議的。

mysql 從 5.0 版本開始,innoDB 存儲引擎已經支持 XA 協議,今天的源碼介紹實驗環境使用的是 mysql 數據庫。

兩階段提交

分布式事務的兩階段提交是把整個事務提交分為 prepare 和 commit 兩個階段。以電商系統為例,分布式系統中有訂單、賬戶和庫存三個服務,如下圖:

第一階段,事務協調者向事務參與者發送 prepare 請求,事務參與者收到請求后,如果可以提交事務,回復 yes,否則回復 no。

第二階段,如果所有事務參與者都回復了 yes,事務協調者向所有事務參與者發送 commit 請求,否則發送 rollback 請求。

兩階段提交存在三個問題:

  • 同步阻塞,本地事務在 prepare 階段鎖定資源,如果有其他事務也要修改 xiaoming 這個賬戶,就必須等待前面的事務完成。這樣就造成了系統性能下降。
  • 協調節點單點故障,如果第一個階段 prepare?成功了,但是第二個階段協調節點發出 commit 指令之前宕機了,所有服務的數據資源處于鎖定狀態,事務將無限期地等待。
  • 數據不一致,如果第一階段 prepare 成功了,但是第二階段協調節點向某個節點發送 commit 命令時失敗,就會導致數據不一致。

三階段提交

為了解決兩階段提交的問題,三階段提交做了改進:

  • 在協調節點和事務參與者都引入了超時機制。
  • 第一階段的 prepare 階段分成了兩步,canCommi 和 preCommit。

如下圖:

引入 preCommit 階段后,協調節點會在 commit 之前再次檢查各個事務參與者的狀態,保證它們的狀態是一致的。但是也存在問題,那就是如果第三階段發出 rollback 請求,有的節點沒有收到,那沒有收到的節點會在超時之后進行提交,造成數據不一致。

XA 事務語法介紹

xa 事務的語法如下:

  • 三階段的第一階段:開啟 xa 事務,這里 xid 為全局事務 id:
  • XA {START|BEGIN} xid [JOIN|RESUME]

    結束 xa 事務:

    XA END xid [SUSPEND [FOR MIGRATE]]
  • 三階段的第二階段,即 prepare:
  • XA PREPARE xid
  • 三階段的第三階段,即 commit/rollback:
  • XA COMMIT xid [ONE PHASE] XA ROLLBACK xid
  • 查看處于 PREPARE 階段的所有事務:
  • XA RECOVER XA RECOVER [CONVERT XID]

    seata?XA 簡介

    seata 是阿里推出的一款開源分布式事務解決方案,目前有 AT、TCC、SAGA、XA 四種模式。

    seata 的 XA 模式是利用分支事務中數據庫對 XA 協議的支持來實現的。我們看一下 seata 官網的介紹:[1]

    從上面的圖可以看到,seata XA 模式的流程跟其他模式一樣:

  • TM 開啟全局事務
  • RM 向 TC?注冊分支事務
  • RM 向 TC 報告分支事務狀態
  • TC?向 RM 發送 commit/rollback 請求
  • TM 結束全局事務
  • 這里介紹一下 RM 客戶端初始化關聯的 UML 類圖:[2]

    這個圖中有一個類是 AbstractNettyRemotingClient,這個類的內部類 ClientHandler 來處理 TC 發來的請求并委托給父類 AbstractNettyRemoting 的 processMessage 方法來處理。processMessage 方法調用 RmBranchCommitProcessor 類的 process 方法。

    需要注意的是,「seata 的 xa 模式對傳統的三階段提交做了優化,改成了兩階段提交」:

    • 第一階段首執行 XA 開啟、執行 sql、XA 結束三個步驟,之后直接執行 XA prepare。
    • 第二階段執行 XA commit/rollback。

    mysql 目前是支持 seata xa 模式的兩階段優化的。

    「但是這個優化對 oracle 不支持,因為 oracle 實現的是標準的 xa 協議,即 xa end 后,協調節點向事務參與者統一發送 prepare,最后再發送 commit/rollback。這也導致了 seata 的 xa 模式對 oracle 支持不太好。」

    seata XA 源碼

    seata 中的 XA 模式是使用數據源代理來實現的,需要手動配置數據源代理,代碼如下:

    @Bean @ConfigurationProperties(prefix = "spring.datasource") public DruidDataSource druidDataSource() {return new DruidDataSource(); }@Bean("dataSourceProxy") public DataSource dataSource(DruidDataSource druidDataSource) {return new DataSourceProxyXA(druidDataSource); }
    • 也可以根據普通 DataSource 來創建 XAConnection,但是這種方式有兼容性問題(比如 oracle),所以 seata 使用了開發者自己配置 XADataSource。
    • seata 提供的 XA 數據源代理,要求代碼框架中必須使用 druid 連接池。

    1. XA 第一階段

    當 RM 收到 DML 請求后,seata 會使用 ExecuteTemplateXA來執行,執行方法 execute 中有一個地方很關鍵,就是把 autocommit 屬性改為了 false,而 mysql 默認 autocommit 是 true。事務提交之后,還要把 autocommit 改回默認。

    下面我們看一下 XA 第一階段提交的主要代碼。

    1)開啟 XA

    上面代碼標注[1]處,調用了 ConnectionProxyXA 類的 setAutoCommit 方法,這個方法的源代碼中,XA start 主要做了三件事:

    • 向 TC 注冊分支事務
    • 調用數據源的 XA Start
    xaResource.start(this.xaBranchXid, XAResource.TMNOFLAGS);
    • 把 xaActive 設置為 true

    RM 并沒有直接使用 TC 返回的 branchId 作為 xa 數據源的 branchId,而是使用全局事務 id(xid) 和 branchId 重新構建了一個。

    2)執行 sql

    調用 PreparedStatementProxyXA 的 execute 執行 sql。

    3)XA end/prepare

    public void commit() throws SQLException {//省略部分源代碼try {// XA End: SuccessxaResource.end(xaBranchXid, XAResource.TMSUCCESS);// XA PreparexaResource.prepare(xaBranchXid);// Keep the Connection if necessarykeepIfNecessary();} catch (XAException xe) {try {// Branch Report to TC: FailedDefaultResourceManager.get().branchReport(BranchType.XA, xid, xaBranchXid.getBranchId(),BranchStatus.PhaseOne_Failed, null);} catch (TransactionException te) {//這兒只打印了一個warn級別的日志}throw new SQLException("Failed to end(TMSUCCESS)/prepare xa branch on " + xid + "-" + xaBranchXid.getBranchId() + " since " + xe.getMessage(), xe);} finally {cleanXABranchContext();} }

    從這個源碼我們看到,commit 主要做了三件事:

    • 調用數據源的 XA end
    • 調用數據源的 XA prepare
    • 向 TC 報告分支事務狀態

    到這里我們就可以看到,seata 把 xa 協議的前兩個階段合成了一個階段。

    2. XA commit

    這里的調用關系用一個時序圖來表示:

    看一下 RmBranchCommitProcessor 類的 process 方法,代碼如下:

    @Override public void process(ChannelHandlerContext ctx, RpcMessage rpcMessage) throws Exception {String remoteAddress = NetUtil.toStringAddress(ctx.channel().remoteAddress());Object msg = rpcMessage.getBody();if (LOGGER.isInfoEnabled()) {LOGGER.info("rm client handle branch commit process:" + msg);}handleBranchCommit(rpcMessage, remoteAddress, (BranchCommitRequest) msg); }

    從調用關系時序圖可以看出,上面的 handleBranchCommit 方法最終調用了 AbstractRMHandler 的 handle 方法,最后通過 branchCommit 方法調用了 ResourceManagerXA 類的 finishBranch 方法。
    ResourceManagerXA 類是 XA 模式的資源管理器,看下面這個類圖,也就是 seata 中資源管理器(RM)的 UML 類圖:

    上面的 finishBranch 方法調用了 connectionProxyXA.xaCommit 方法,我們最后看一下 xaCommit 方法:

    public void xaCommit(String xid, long branchId, String applicationData) throws XAException {XAXid xaXid = XAXidBuilder.build(xid, branchId);//因為使用mysql,這里xaResource是MysqlXAConnectionxaResource.commit(xaXid, false);releaseIfNecessary(); }

    上面調用了數據源的 commit 方法,提交了 RM 分支事務。

    到這里,整個 RM 分支事務就結束了。Rollback 的代碼邏輯跟 commit 類似。

    最后要說明的是,上面的 xaResource,是 mysql-connector-java.jar 包中的 MysqlXAConnection 類實例,它封裝了 mysql 提供的 XA 協議接口。

    總結

    seata 中 XA 模式的實現是使用數據源代理完成的,底層使用了數據庫對 XA 協議的原生支持。

    mysql 的 java 驅動庫中,MysqlXAConnection 類封裝類 XA 協議的底層接口供外部調用。

    跟 TCC 和 SAGA 模式需要在業務代碼中實現 prepare/commit/rollback 邏輯相比,XA 模式對業務代碼無侵入。

    Reference

    [1]:http://seata.io/zh-cn/docs/overview/what-is-seata.html
    [2]:https://github.com/seata/seata

    總結

    以上是生活随笔為你收集整理的6 张图带你彻底搞懂分布式事务 XA 模式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 午夜影院免费看 | 国产67194| 成人做受黄大片 | 97狠狠干 | 男人天堂影院 | 九色视频自拍 | 最新永久地址 | 国产精品人妻一区二区三区 | 伊人久久青青 | 综合久久久久久久 | 动漫羞羞 | 日本簧片在线观看 | 亚洲精品在线视频免费观看 | 麻豆国产尤物av尤物在线观看 | 999久久久| 天天天天 | 成人在线视频免费观看 | 欧美性猛交xxxx黑人猛交 | 国产精品成人av性教育 | 高潮毛片无遮挡高清免费 | 爱爱一区二区三区 | 五月天精品 | 在线干| 色七七在线 | 色综合中文综合网 | 丰满岳乱妇在线观看中字无码 | 337p亚洲欧洲色噜噜噜 | 国产一级α片 | 中文字幕在线日韩 | 久久久久久久久99 | 91香蕉国产在线观看软件 | 婷婷激情综合网 | 日韩小视频在线 | 欧美性爱精品在线 | 伊人三级| 亚洲狠狠婷婷综合久久久久图片 | 亚洲综合图片一区 | 波多野结衣视频一区 | 三级不卡 | 欧美一区二区三区久久妖精 | 精品一级少妇久久久久久久 | 亲嘴扒胸摸屁股免费视频日本网站 | 鲁丝一区二区三区 | 亚洲成人自拍网 | 亚洲黄色录像 | 国产在线一二区 | 亚洲av无码片一区二区三区 | 四虎免费在线观看 | 九一精品在线 | 怡红院成永久免费人全部视频 | 国产熟女高潮一区二区三区 | 国产爽爽视频 | 成人乱码一区二区三区av | 黄色片xxx | 久久精品免费 | 人妻射精一区二区 | 国产人妻一区二区三区四区五区六 | 国产午夜电影 | 久久久噜噜噜久久中文字幕色伊伊 | 国产精品高潮呻吟视频 | 欧美gv在线观看 | 毛片免费在线观看视频 | 丰满人妻老熟妇伦人精品 | 国产精品乱码一区二区三区 | 在线免费 | 四虎影院在线 | 不卡视频一区二区 | 国语对白少妇spa私密按摩 | 无码人妻丰满熟妇啪啪网站 | 麻豆视频国产 | 久久精品视频一区 | 最新黄色av | 少妇精品视频一区二区 | 久久精品2| 色偷偷中文字幕 | 天堂8中文 | 综合国产视频 | 99久久久久久 | 精品国产乱码久久久久久浪潮 | 国产精品88| 国产欧美久久一区二区三区 | 成人午夜精品无码区 | 午夜肉伦伦影院 | 精品国产99久久久久久 | v在线| 麻豆疯狂做受xxxx高潮视频 | 99国产揄拍国产精品 | 女同动漫免费观看高清完整版在线观看 | 亚洲精久久 | 欧美成视频 | 亚洲一区中文字幕在线 | 亚洲色妞| 五月婷婷天 | 欧美在线不卡视频 | 噜噜噜噜噜色 | 爱爱短视频 | 日本夜夜操 | 在线观看日本中文字幕 | 在线毛片网 |