分布式事務之Seata

概述

Seata有四種模式

AT模式:無侵入式的分布式事務解決方案,適合不希望對業務進行改造的場景,但由于需要添加全局事務鎖,對影響高并發系統的性能。該模式主要關注多DB訪問的數據一致性,也包括多服務下的多DB數據訪問一致性問題。通過更新前快照回滾、更新后快照對比在二階段提交時是否有人修改(為不受Seata代理的數據源做兜底),解決臟寫。

優點:

  • 一階段完成直接提交事務,釋放數據庫資源,性能比較好

  • 利用全局鎖實現讀寫隔離

  • 沒有代碼侵入,框架自動完成回滾和提交

缺點:

  • 兩階段之間屬于軟狀態,屬于最終一致

  • 框架的快照功能會影響性能,但比XA模式要好很多

TCC模式:高性能的分布式事務解決方案,適用于對性能要求比較高的場景。該模式主要關注業務拆分,在按照業務橫向擴展資源時,解決服務間調用的一致性問題。

優點:

  • 一階段完成直接提交事務,釋放數據庫資源,性能好
  • 相比AT模型,無需生成快照,無需使用全局鎖,性能最強
  • 不依賴數據庫事務,而是依賴補償操作,可以用于非事務型數據庫
  • Redis這種也可以使用TCC模式

缺點:

  • 有代碼侵入,需要人為編寫try、Confirm和Cancel接口,太麻煩
  • 軟狀態,事務是最終一致
  • 需要考慮Confirm和Cancel的失敗情況,做好冪等處理
  • 因為如果失敗Seata會重試,所有要做好冪等

Saga模式:長事務的分布式事務解決方案,適用于業務流程長且需要保證事務最終一致性的業務系統。Saga 模式一階段就會提交本地事務,無鎖,長流程情況下可以保證性能,多用于渠道層、集成層業務系統,事務參與者可以是其它公司的服務也可以是遺留系統的服務,并且對于無法進行改造和提供 TCC 要求的接口,也可以使用 Saga 模式。

優點:

  • 一階段提交本地數據庫事務,無鎖,高性能;

  • 參與者可以采用事務驅動異步執行,高吞吐;

  • 補償服務即正向服務的“反向”,易于理解,易于實現;

缺點:

  • Saga 模式由于一階段已經提交本地數據庫事務,且沒有進行“預留”動作,所以不能保證隔離性。后續會講到對于缺乏隔離性的應對措施。

XA模式:強一致性。XA早期版本是一種規范 主流數據庫對XA規范提供了支持,沒有TM(事務管理者的概念)只有TC和RM。一階段不提交事務,在第二階段TM發起事務提交/回滾時才會讓TC檢查分支狀態做提交/回滾因此是強一致性的

優點:

  • 強一致性
  • 易于使用:因為主流數據庫都支持且無代碼侵入

缺點:

  • 第一階段不提交,在等待過程中占用數據庫鎖,占用系統資源,性能差

Seata核心組件

  • TC(Transaction Coordinator):全局事務協調器,負責管理全局事務的狀態。
  • TM(Transaction Manager):事務管理器,負責發起全局事務,并向TC注冊事務。
  • RM(Resource Manager):資源管理器,負責管理資源的本地事務,并向TC匯報事務狀態。

前置條件

  1. 引入Seata依賴:在項目中引入Seata的依賴。
  2. 配置Seata服務:配置Seata的TC服務地址。
  3. 定義全局事務:使用@GlobalTransactional注解定義全局事務。

1. AT 模式(Auto Transaction)?

核心原理

  • ?兩階段提交:

  1. ?階段一(Branch Commit)?:攔截業務 SQL,生成前置鏡像(before image)和后置鏡像(after image),保存到 UNDO_LOG 表。
    示例:執行 UPDATE product SET stock = stock - 10 WHERE id = 1 時,記錄修改前的 stock=100 和修改后的 stock=90。
  2. 階段二(Global Commit/Rollback)?:全局事務提交時,刪除 UNDO_LOG;回滾時,根據鏡像數據生成反向SQL(如 UPDATE product SET stock = 100 WHERE id = 1)。
  • ?全局鎖機制:

在階段一提交前,Seata 會獲取記錄的全局鎖,防止其他事務修改同一數據,確保隔離性。

?應用場景

  • 單服務多數據源:

????????例如訂單服務同時操作 MySQL 和 PostgreSQL,需要保證兩個庫的事務一致性。

  • ?簡單跨服務調用:

????????服務 A 調用服務 B 的接口,兩者均使用 AT 模式(如訂單服務扣減庫存服務)。

代碼示例

// 訂單服務(使用 AT 模式)
@GlobalTransactional // 開啟全局事務
public void saveOrder(OrderRequest request) {// 1. 本地事務:創建訂單orderDao.insert(request.getOrder());// 2. 遠程調用庫存服務(Feign 接口)storageFeign.discount(request.getProductId(), request.getCount());// 3. 模擬異常觸發回滾if (request.getForceFail()) {throw new RuntimeException("Force rollback");}
}

關鍵細節

  • UNDO_LOG 表結構:需在業務庫中提前創建,包含 branch_id、xid、rollback_info 等字段。
  • ?隔離性犧牲:AT 模式默認隔離級別為讀未提交(Read Uncommitted),高并發場景可能臟讀,需業務側處理(如版本號校驗)。
  • ?性能優化:避免單行數據頻繁更新,防止全局鎖競爭。

?2. TCC 模式(Try-Confirm-Cancel)?

核心原理

三階段控制:

?Try:預留資源(如凍結庫存、預扣余額),完成業務檢查。
?Confirm:確認操作,真正執行業務(如扣減凍結的庫存)。
?Cancel:回滾操作,釋放預留資源(如解凍庫存)。

業務侵入性:需手動編寫 Try/Confirm/Cancel 接口,處理冪等性、空回滾、懸掛等問題。

?應用場景

  • ?資金交易:轉賬前預凍結賬戶金額,最終扣款或解凍。
  • ?第三方服務集成:調用外部 API(如支付接口)需要明確的成功/失敗確認。

?代碼示例

// TCC 接口定義(賬戶扣款)
public interface AccountTccService {@TwoPhaseBizAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")boolean tryDiscount(@BizActionContextParameter(paramName = "userId") String userId,@BizActionContextParameter(paramName = "amount") BigDecimal amount);boolean confirm(BizActionContext context);boolean cancel(BizActionContext context);
}// Try 階段實現(凍結資金)
@Override
public boolean tryDeduct(String userId, BigDecimal amount) {if (accountDao.getAvailableBalance(userId).compareTo(amount) < 0) {throw new RuntimeException("余額不足");}accountDao.freeze(userId, amount); // 凍結資金return true;
}// Confirm 階段(實際扣款)
@Override
public boolean confirm(BizActionContext context) {String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountDao.discount(userId, amount); ?// 扣減凍結金額accountDao.unfreeze(userId, amount); // 解凍return true;
}// Cancel 階段(解凍資金)
@Override
public boolean cancel(BizActionContext context) {String userId = (String) context.getActionContext("userId");BigDecimal amount = (BigDecimal) context.getActionContext("amount");accountDao.unfreeze(userId, amount);return true;
}

?關鍵細節

  • ?冪等性處理:
    通過唯一事務 ID(xid)確保 Confirm/Cancel 只執行一次。
  • ?空回滾問題:
    Try 未執行但收到 Cancel 請求時,需插入標記記錄,避免誤解凍。
  • ?懸掛問題:
    Cancel 比 Try 先到達時,需通過狀態判斷拒絕后續 Try 操作。

?3. Saga 模式

?核心原理

  • 事件驅動流程:
    將分布式事務拆分為多個本地事務,每個事務提交后觸發下一個事務。若某個事務失敗,按反向順序執行補償操作。
  • ?補償機制:
    每個正向操作需定義對應的補償方法(如 bookHotel() 對應 cancelHotel())。

?應用場景

  • ?長流程業務:
    旅行預訂(機票 → 酒店 → 租車)、電商訂單(下單 → 支付 → 發貨)。
  • 渠道層、集成層業務:
    在渠道層和集成層業務中,往往需要與外部系統進行交互。例如,銀行系統與第三方支付平臺的集成,或者企業系統與ERP系統的集成。這些場景中,事務的跨服務特性使得Saga模式成為理想的解決方案。
  • ?跨公司服務集成:
    跨公司服務集成中,事務的分布式特性更加明顯。例如,一個供應鏈系統可能涉及多個供應商、物流和零售商的協作。Saga模式通過補償機制,可以有效地處理這些復雜場景中的事務問題。
  • 最終一致性場景:
    接受中間狀態短暫不一致,但最終一致。Saga模式通過補償操作保證最終一致性。如果某個Saga單元失敗,系統會依次調用之前所有單元的補償操作,回滾之前的操作。例如,如果支付服務扣款失敗,系統會調用庫存服務的補償操作恢復庫存。

?代碼示例

//Saga 流程編排(狀態機或注解驅動)
@SagaService
public class OrderSagaService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate PaymentService paymentService;@SagaStartpublic void createOrder(Order order) {// 1. 扣減庫存inventoryService.discount(order.getProductId(), order.getQuantity());// 2. 發起支付paymentService.pay(order.getUserId(), order.getAmount());// 3. 更新訂單狀態為成功order.setStatus(OrderStatus.SUCCESS);orderDao.update(order);}@Compensatepublic void compensateOrder(Order order) {// 反向操作:釋放庫存、退款、訂單狀態回滾inventoryService.restore(order.getProductId(), order.getQuantity());paymentService.refund(order.getUserId(), order.getAmount());order.setStatus(OrderStatus.FAILED);orderDao.update(order);}
}

關鍵細節

  • ?狀態機配置:
    可通過 JSON 或注解定義 Saga 流程,明確每個步驟的補償方法。
  • ?超時管理:
    設置 Saga 事務超時時間,避免流程長期懸掛。
  • ?異步執行:
    適合結合消息隊列(如 RocketMQ)實現異步 Saga。

?注:@Compensate

4. XA 模式

核心原理

  • ?傳統兩階段提交:
    ? Prepare 階段:所有參與者(數據庫)鎖定資源,返回就緒狀態。
    ??Commit/Rollback 階段:協調者根據 Prepare 結果提交或回滾。
  • ?強一致性:
    所有資源在 Prepare 階段鎖定,直到全局事務結束。

?應用場景

  • ?金融核心系統:
    銀行轉賬(必須保證雙方賬戶同時成功或失敗)。
  • ?傳統數據庫集成:
    舊系統遷移,依賴數據庫原生 XA 協議。

?代碼示例

// XA 數據源配置
@Bean
public DataSource dataSource() {MysqlXADataSource xaDataSource = new MysqlXADataSource();xaDataSource.setUrl("jdbc:mysql://localhost:3306/test");xaDataSource.setUser("root");xaDataSource.setPassword("***");return new AtomikosDataSourceBean(xaDataSource);
}// 業務方法(依賴 JTA)
@Transactional // 使用 JTA 事務管理器
public void transfer(String fromId, String toId, BigDecimal amount) {jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);
}

關鍵細節

  • ?性能瓶頸:
    全局鎖持有時間長,高并發下吞吐量低。
  • ?數據庫支持:
    需數據庫支持 XA 協議(如 MySQL InnoDB、Oracle)。
  • ?調試復雜:
    XA 事務狀態需通過數據庫日志或 JTA 工具監控。

選型對比

?對比維度

維度ATTCC?? ?SagaXA
?一致性弱隔離(讀未提交)強隔離(預留資源)最終一致性強一致性
?性能高(短事務)?中(兩階段控制)高(異步流程)低(長鎖)
?侵入性低(自動 UNDO_LOG)高(手動 TCC 接口)中(補償方法)低(數據庫支持)
適用場景?簡單跨服務/多數據源?資金交易、第三方集成長流程業務金融核心、傳統系統
?容錯能力自動回滾需處理空回滾、懸掛需補償邏輯完備依賴數據庫 XA 恢復

決策樹

  • 是否需要強一致性?
    是 → ?XA 模式?(金融場景)或 ?TCC 模式?(業務可控)。
    否 → 進入下一步。
  • ?是否為長流程業務?
    是 → ?Saga 模式?(如電商訂單)。
    否 → 進入下一步。
  • ?是否希望低侵入?
    是 → ?AT 模式?(簡單跨服務調用)。
    否 → ?TCC 模式?(精細化控制)。

?總結

  • AT 模式:快速解決 80% 的分布式事務問題,適合微服務新手。
  • ?TCC 模式:應對資金、庫存等核心資源操作,犧牲開發效率換取高可靠性。
  • ?Saga 模式:長流程業務的終極方案,需接受最終一致性。
  • ?XA 模式:傳統系統兼容選擇,性能敏感場景慎用。

? ? 實際開發中,多種模式在同一個工程中不可混用、不能同時使用,但可組合使用多種模式(如 AT + Saga),并配合消息隊列、冪等設計、監控告警,構建健壯的分布式事務體系。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81184.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81184.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

信息收集與搜索引擎

6.1 常見的搜索引擎&#xff08;一、二&#xff09; 6.1.1 通用搜索引擎 Google/Bing&#xff1a; 用途&#xff1a;基礎信息收集&#xff08;域名、子域名、敏感文件&#xff09;。 高級語法&#xff1a; site:target.com&#xff1a;限定搜索目標域名。 filetype:pdf&am…

【Java項目測試報告】:在線聊天平臺(Online-Chat)

被測試項目已部署&#xff1a;登錄頁面http://123.249.78.82:8080/login.html 一、項目背景 1.1 測試目標 驗證系統功能完整性&#xff0c;確保用戶管理、消息傳輸、好友管理等核心模塊符合需求。 1.2 項目技術棧 后端&#xff1a;Spring Boot/Spring MVC/WebSocket 數據…

RAGFlow與Dify的深度刨析

目錄 一、RAGFlow 框架 二、Dify 框架 三、兩者集成 四、深度對比 1. 核心定位對比 2. 核心功能對比 3. 技術架構對比 4. 部署與成本 5. 適用場景推薦 總結 一、RAGFlow 框架 RAGFlow 是一個專注于深度文檔理解和檢索增強生成&#xff08;RAG&#xff09;技術的框架…

CQF預備知識:一、微積分 -- 1.2.2 函數f(x)的類型詳解

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 &#x1f4d6; 數學入門全解 本系列教程為CQF(國際量化金融分析師證書)認證所需的數學預備知識&#xff0c;涵蓋所有需要了解的數學基礎知識…

嵌入式工程師常用軟件

1、 Git Git 是公司常用的版本管理工具&#xff0c;人人都要會。在線的 git 教程可以參考菜鳥教程&#xff1a; https://www.runoob.com/git/git-tutorial.html 電子書教程請在搜索欄搜索&#xff1a; git Git 教程很多&#xff0c;常用的命令如下&#xff0c;這些命令可…

TReport組件指南總結

1. TReport 組件簡介 TReport 是一個用于生成和打印報表的組件,通常用于連接數據集(如 TDataSet)并設計復雜的報表布局。它支持動態數據綁定、多頁報表、分組統計、圖表插入等功能。 2. 安裝與配置 安裝:如果使用的是第三方報表工具(如 Rave Reports),需在 Delphi 中通…

spark任務的提交流程

目錄 spark任務的提交流程1. 資源申請與初始化2. 任務劃分與調度3. 任務執行4. 資源釋放與結果處理附:關鍵組件協作示意圖擴展說明SparkContext介紹 spark任務的提交流程 用戶創建一個 Spark Context;Spark Context 去找 Cluster Manager 申請資源同時說明需要多少 CPU 和內…

【C++】C++異步編程四劍客:future、async、promise和packaged_task詳解

C異步編程四劍客&#xff1a;future、async、promise和packaged_task詳解 1. 引言 1.1 異步編程的重要性 在現代C編程中&#xff0c;異步操作是提高程序性能和響應能力的關鍵技術。它允許程序在等待耗時操作&#xff08;如I/O、網絡請求或復雜計算&#xff09;完成時繼續執行…

2021-10-28 C++判斷完全平方數

緣由判斷一個整數是否為完全平方數-編程語言-CSDN問答 整數用平方法小數用5分法逼近。 int 判斷平方數(int n) {//緣由https://ask.csdn.net/questions/7546950?spm1005.2025.3001.5141int a 1;while (a < n / a)if (a*a < n)a;else if (a*a n)return 1;elsereturn 0…

解決weman框架redis報錯:Class “llluminatelRedis\RedisManager“ not found

解決weman框架redis報錯&#xff1a;Class "llluminatelRedis\RedisManager" not found 報錯解決方案 報錯 解決方案 按照手冊執行 composer require psr/container ^1.1.1 illuminate/redis illuminate/events 安裝redis組件 然后restart重啟就行了 php webman s…

Windows 11 電源計劃進階——通過異類策略優化大小核CPU調度

一、為什么需要手動控制大小核調度&#xff1f; 1.1 Intel 12/13/14代酷睿與Win11的適配現狀 Intel 12代酷睿首次引入混合架構設計&#xff08;P-Core性能核 E-Core能效核&#xff09;&#xff0c;Windows 11雖然原生支持線程調度器&#xff08;Thread Director&#xff09;…

文件系統·linux

目錄 磁盤簡介 Ext文件系統 塊 分區 分組 inode 再談inode 路徑解析 路徑緩存 再再看inode 掛載 小知識 磁盤簡介 磁盤&#xff1a;一個機械設備&#xff0c;用于儲存數據。 未被打開的文件都是存在磁盤上的&#xff0c;被打開的加載到內存中。 扇區&#xff1a;是…

如何使用redis做限流(golang實現小樣)

在實際開發中,限流(Rate Limiting)是一種保護服務、避免接口被惡意刷流的常見技術。常用的限流算法有令牌桶、漏桶、固定窗口、滑動窗口等。由于Redis具備高性能和原子性操作,常常被用來實現分布式限流。 下面給出使用Golang結合Redis實現簡單限流的幾種常見方式(以“固定…

手寫ES6 Promise() 相關函數

手寫 Promise() 相關函數&#xff1a; Promise()、then()、catch()、finally() // 定義三種狀態常量 const PENDING pending const FULFILLED fulfilled const REJECTED rejectedclass MyPromise {/*定義狀態和結果兩個私有屬性:1.使用 # 語法&#xff08;ES2022 官方私有字…

Redis學習專題(五)緩存穿透、緩存擊穿、緩存雪崩

目錄 一、緩存穿透 緩存穿透的原因&#xff1a; 緩存穿透的現象&#xff1a; 緩存穿透的解決辦法&#xff1a; 二、緩存擊穿 緩存擊穿的原因&#xff1a; 緩存擊穿的現象&#xff1a; 緩存擊穿的解決辦法: 三、緩存雪崩 緩存雪崩的原因&#xff1a; 緩存雪崩的現象&…

【Hadoop】大數據技術之 MapReduce

目錄 一、MapReduce概述 1.1 MapReduce 定義 1.2 MapReduce優缺點 1.3 MapReduce 核心思想 1.4 MapReduce 進程 1.5 常用數據序列化類型 1.6 MapReduce 編程規范 二、WordCound 案例 2.1 環境準備 2.2 編寫程序 三、MapReduce 工作流程 一、MapReduce概述 1.1 MapRe…

國際前沿知識系列三:解決泛化能力不足問題

目錄 國際前沿知識系列三&#xff1a;解決泛化能力不足問題 一、子類建模法與分類建模法在腦區應變預測中的應用 &#xff08;一&#xff09;子類建模法 案例分析 &#xff08;二&#xff09;分類建模法 案例分析 二、基于遷移學習和數據融合的大腦應變預測模型改良 &a…

client.chat.completions.create方法參數詳解

response client.chat.completions.create(model"gpt-3.5-turbo", # 必需參數messages[], # 必需參數temperature1.0, # 可選參數max_tokensNone, # 可選參數top_p1.0, # 可選參數frequency_penalty0.0, # 可選參數presenc…

iOS 15.4.1 TrollStore(巨魔商店)安裝教程詳解:第二篇

?? iOS 15.4.1 TrollStore(巨魔商店)安裝教程詳解 ? 前言??? 如何安裝 TrollStore?第一步:打開 Safari 瀏覽器第二步:選擇對應系統版本安裝方式第三步:訪問地址,下載配置文件(plist)第四步:安裝配置文件第五步:“jailbreaks.app” 請求安裝 TrollHelper第六步…

SQL的RAND用法和指定生成隨機數的范圍

SQL中的RAND函數能夠滿足多種隨機數生成的需求。通過合理地使用種子、結合一些SQL語句&#xff0c;我們可以實現靈活的隨機數生成。在數據填充、數據處理、數據分析中經常需要用RAND生成的隨機數。 用法1 生成隨機浮點數&#xff0c;其返回值在0&#xff08;包括0&#xff09;…