Seata之分布式事務問題及解決方案
Seata–分布式事務解決方案
簡介
Seata 是阿里開源的分布式事務解決方案,提供 AT、XA、TCC、Saga 四種事務模式,支持微服務架構下的數(shù)據一致性。
官網:https://seata.apache.org/zh-cn/
同類產品對比
方案 | 核心特點 | 適用場景 |
---|---|---|
Seata | 多模式支持,代碼侵入性低,社區(qū)活躍 | 復雜業(yè)務場景,需靈活選擇模式 |
阿里云 GTS | 商業(yè)版方案,功能全面,性能強 | 企業(yè)級付費場景 |
RocketMQ 事務消息 | 基于消息隊列實現(xiàn)最終一致性 | 異步高吞吐場景 |
LCN | 基于代理模式,實現(xiàn)簡單 | 輕量級快速接入 |
環(huán)境搭建
1.微服務
創(chuàng)建 Spring Cloud 項目,推薦使用以下組件:
<!-- Spring Cloud Alibaba 依賴 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
2.SQL
每個微服務數(shù)據庫需創(chuàng)建 undo_log 表(AT模式必需):
-- 每個業(yè)務數(shù)據庫均需執(zhí)行 CREATE TABLE IF NOT EXISTS `undo_log` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `branch_id` BIGINT(20) NOT NULL, `xid` VARCHAR(100) NOT NULL, `context` VARCHAR(128) NOT NULL, `rollback_info` LONGBLOB NOT NULL, `log_status` INT(11) NOT NULL, `log_created` DATETIME NOT NULL, `log_modified` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
3.seata-server
- 1.下載 :https://seata.apache.org/zh-cn/download/seata-server
- 2.解壓并啟動:seata-server.bat
- 3.控制臺:http://127.0.0.1:7091/#/transaction/list
4.微服務配置
依賴
除基礎依賴外需添加:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
配置
每個微服務創(chuàng)建 file.conf
文件,完整內容如下;
【微服務只需要復制 service 塊
配置即可】
# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # transport { # tcp, unix-domain-socket type = "TCP" #NIO, NATIVE server = "NIO" #enable heartbeat heartbeat = true # the tm client batch send request enable enableTmClientBatchSendRequest = false # the rm client batch send request enable enableRmClientBatchSendRequest = true # the rm client rpc request timeout rpcRmRequestTimeout = 2000 # the tm client rpc request timeout rpcTmRequestTimeout = 30000 # the rm client rpc request timeout rpcRmRequestTimeout = 15000 #thread factory for netty threadFactory { bossThreadPrefix = "NettyBoss" workerThreadPrefix = "NettyServerNIOWorker" serverExecutorThread-prefix = "NettyServerBizHandler" shareBossWorker = false clientSelectorThreadPrefix = "NettyClientSelector" clientSelectorThreadSize = 1 clientWorkerThreadPrefix = "NettyClientWorkerThread" # netty boss thread size bossThreadSize = 1 #auto default pin or 8 workerThreadSize = "default" } shutdown { # when destroy server, wait seconds wait = 3 } serialization = "seata" compressor = "none" } service { #transaction service group mapping vgroupMapping.default_tx_group = "default" #only support when registry.type=file, please don't set multiple addresses default.grouplist = "127.0.0.1:8091" #degrade, current not support enableDegrade = false #disable seata disableGlobalTransaction = false } client { rm { asyncCommitBufferLimit = 10000 lock { retryInterval = 10 retryTimes = 30 retryPolicyBranchRollbackOnConflict = true } reportRetryCount = 5 tableMetaCheckEnable = false tableMetaCheckerInterval = 60000 reportSuccessEnable = false sagaBranchRegisterEnable = false sagaJsonParser = "fastjson" sagaRetryPersistModeUpdate = false sagaCompensatePersistModeUpdate = false tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 sqlParserType = "druid" branchExecutionTimeoutXA = 60000 connectionTwoPhaseHoldTimeoutXA = 10000 } tm { commitRetryCount = 5 rollbackRetryCount = 5 defaultGlobalTransactionTimeout = 60000 degradeCheck = false degradeCheckPeriod = 2000 degradeCheckAllowTimes = 10 interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 } undo { dataValidation = true onlyCareUpdateColumns = true logSerialization = "jackson" logTable = "undo_log" compress { enable = true # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip type = zip # if rollback info size > threshold, then will be compress # allow k m g t threshold = 64k } } loadBalance { type = "XID" virtualNodes = 10 } } log { exceptionRate = 100 } tcc { fence { # tcc fence log table name logTableName = tcc_fence_log # tcc fence log clean period cleanPeriod = 1h } }
事務模式
1.AT模式(推薦:自動補償)
二階提交協(xié)議原理
原理:基于反向SQL補償,自動生成回滾日志
使用:
@Service public class OrderService { @GlobalTransactional(name = "createOrder", timeoutMills = 60000) public void createOrder(OrderDTO order) { // 1. 扣減庫存(調用庫存服務) storageFeignClient.deduct(order.getProductId()); // 2. 創(chuàng)建訂單(本地事務) orderMapper.insert(order); // 3. 模擬異常觸發(fā)回滾 int i = 1 / 0; } }
關鍵機制:
- 一階段:提交本地事務,生成回滾日志(undo_log)
- 二階段:成功則異步刪除日志,失敗則通過日志反向補償
特點:
- 對代碼無侵入
- 需創(chuàng)建undo_log表
- 適用于大多數(shù)CRUD場景
2.XA模式(強一致)
原理:基于數(shù)據庫XA協(xié)議的兩階段提交
配置:
seata: data-source-proxy-mode: XA # 默認AT
特點:
- 基于數(shù)據庫XA協(xié)議
- 兩階段提交(2PC)
- 事務持有鎖時間較長,適合短事務
適用場景:強一致性需求,支持XA協(xié)議的數(shù)據庫(如MySQL 5.7+)
3.TCC模式(手動補償)
原理:Try-Confirm-Cancel 三階段控制
實現(xiàn):
// 1. 定義TCC接口 public interface StorageTccService { @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel") boolean deduct(@BusinessActionContextParameter(paramName = "productId") String productId, @BusinessActionContextParameter(paramName = "count") Integer count); boolean confirm(BusinessActionContext context); boolean cancel(BusinessActionContext context); } // 2. 實現(xiàn)Try邏輯 @Service public class StorageTccServiceImpl implements StorageTccService { @Override public boolean deduct(String productId, Integer count) { // Try階段:資源預留(例如凍結庫存) return storageMapper.freezeStock(productId, count) > 0; } @Override public boolean confirm(BusinessActionContext context) { // Confirm階段:真實扣減(例如刪除凍結記錄) String productId = context.getActionContext("productId"); Integer count = context.getActionContext("count"); return storageMapper.reduceStock(productId, count) > 0; } @Override public boolean cancel(BusinessActionContext context) { // Cancel階段:釋放資源(例如恢復凍結庫存) String productId = context.getActionContext("productId"); Integer count = context.getActionContext("count"); return storageMapper.unfreezeStock(productId, count) > 0; } }
使用限制:
- 需自行實現(xiàn)Try/Confirm/Cancel方法
- Confirm和Cancel需保證冪等性
特點:高性能,但需手動編寫補償邏輯
4.Saga模式(長事務)
實現(xiàn)方式:
通過狀態(tài)機配置補償策略:
@SagaStart public void createOrderSaga(Order order) { // 1. 創(chuàng)建訂單 orderService.create(order); // 2. 調用支付服務(若失敗則觸發(fā)逆向操作) paymentService.pay(order.getId()); } // 定義補償方法 @Compensate public void compensateOrder(Order order) { orderService.delete(order.getId()); }
原理:長事務拆分+逆向補償
適用場景:跨系統(tǒng)長時間操作(如訂單+物流+支付)
總結
模式選型對照表:
模式 | 一致性 | 性能 | 侵入性 | 適用場景 |
---|---|---|---|---|
AT | 弱一致 | 高 | 低 | 常規(guī)業(yè)務(庫存扣減、訂單創(chuàng)建) |
TCC | 強一致 | 中 | 高 | 資金交易、需精準控制 |
XA | 強一致 | 低 | 低 | 銀行轉賬、短事務 |
Saga | 最終一致 | 高 | 中 | 跨系統(tǒng)長流程(訂單+物流+支付) |
核心要點:
分類 | 要點說明 |
---|---|
選型 | AT模式適用于大多數(shù)場景,TCC適合高性能要求,XA適合強一致性 |
配置 | 確保seata-server與微服務的registry配置一致 |
事務ID | 通過RootContext.getXID()可獲取當前事務ID |
排錯 | 檢查undo_log表記錄,查看seata-server控制臺日志 |
最佳實踐:
- 生產環(huán)境建議使用Nacos作為配置中心
- AT模式需要開啟數(shù)據庫的本地事務支持(如MySQL的InnoDB引擎)
- 全局事務超時時間建議設置:
seata.tx.timeout=60000
(單位毫秒)
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
postman?如何實現(xiàn)傳遞?ArrayList?給后臺
這篇文章主要介紹了postman?如何實現(xiàn)傳遞?ArrayList給后臺,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12關于Java并發(fā)編程中線程間協(xié)作的兩種方式
這篇文章主要介紹了關于Java并發(fā)編程中線程間協(xié)作的兩種方式,當隊列滿時,生產者需要等待隊列有空間才能繼續(xù)往里面放入商品,而在等待的期間內,生產者必須釋放對臨界資源的占用權,這是消費者模式,需要的朋友可以參考下2023-07-07Spring Cloud Gateway 內存溢出的解決方案
這篇文章主要介紹了Spring Cloud Gateway 內存溢出的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Spring-Cloud Eureka注冊中心實現(xiàn)高可用搭建
這篇文章主要介紹了Spring-Cloud Eureka注冊中心實現(xiàn)高可用搭建,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04