概述
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匯報事務狀態。
前置條件
- 引入Seata依賴:在項目中引入Seata的依賴。
- 配置Seata服務:配置Seata的TC服務地址。
- 定義全局事務:使用
@GlobalTransactional
注解定義全局事務。
1. AT 模式(Auto Transaction)?
核心原理
-
?兩階段提交:
- ?階段一(Branch Commit)?:攔截業務 SQL,生成前置鏡像(before image)和后置鏡像(after image),保存到 UNDO_LOG 表。
示例:執行 UPDATE product SET stock = stock - 10 WHERE id = 1 時,記錄修改前的 stock=100 和修改后的 stock=90。- 階段二(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 工具監控。
選型對比
?對比維度
維度 | AT | TCC?? ? | Saga | XA |
?一致性 | 弱隔離(讀未提交) | 強隔離(預留資源) | 最終一致性 | 強一致性 |
?性能 | 高(短事務) | ?中(兩階段控制) | 高(異步流程) | 低(長鎖) |
?侵入性 | 低(自動 UNDO_LOG) | 高(手動 TCC 接口) | 中(補償方法) | 低(數據庫支持) |
適用場景 | ?簡單跨服務/多數據源 | ?資金交易、第三方集成 | 長流程業務 | 金融核心、傳統系統 |
?容錯能力 | 自動回滾 | 需處理空回滾、懸掛 | 需補償邏輯完備 | 依賴數據庫 XA 恢復 |
決策樹
- 是否需要強一致性?
是 → ?XA 模式?(金融場景)或 ?TCC 模式?(業務可控)。
否 → 進入下一步。 - ?是否為長流程業務?
是 → ?Saga 模式?(如電商訂單)。
否 → 進入下一步。 - ?是否希望低侵入?
是 → ?AT 模式?(簡單跨服務調用)。
否 → ?TCC 模式?(精細化控制)。
?總結
- AT 模式:快速解決 80% 的分布式事務問題,適合微服務新手。
- ?TCC 模式:應對資金、庫存等核心資源操作,犧牲開發效率換取高可靠性。
- ?Saga 模式:長流程業務的終極方案,需接受最終一致性。
- ?XA 模式:傳統系統兼容選擇,性能敏感場景慎用。
? ? 實際開發中,多種模式在同一個工程中不可混用、不能同時使用,但可組合使用多種模式(如 AT + Saga),并配合消息隊列、冪等設計、監控告警,構建健壯的分布式事務體系。