seata–分布式事务解决方案
简介
seata 是阿里开源的分布式事务解决方案,提供 at、xa、tcc、saga 四种事务模式,支持微服务架构下的数据一致性。
官网:https://seata.apache.org/zh-cn/
同类产品对比
| 方案 | 核心特点 | 适用场景 |
|---|---|---|
| seata | 多模式支持,代码侵入性低,社区活跃 | 复杂业务场景,需灵活选择模式 |
| 阿里云 gts | 商业版方案,功能全面,性能强 | 企业级付费场景 |
| rocketmq 事务消息 | 基于消息队列实现最终一致性 | 异步高吞吐场景 |
| lcn | 基于代理模式,实现简单 | 轻量级快速接入 |
环境搭建
1.微服务
创建 spring cloud 项目,推荐使用以下组件:
<!-- spring cloud alibaba 依赖 -->
<dependency>
<groupid>com.alibaba.cloud</groupid>
<artifactid>spring-cloud-starter-alibaba-seata</artifactid>
</dependency>2.sql
每个微服务数据库需创建 undo_log 表(at模式必需):
-- 每个业务数据库均需执行
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>
配置
每个微服务创建 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模式(推荐:自动补偿)
二阶提交协议原理
原理:基于反向sql补偿,自动生成回滚日志

使用:
@service
public class orderservice {
@globaltransactional(name = "createorder", timeoutmills = 60000)
public void createorder(orderdto order) {
// 1. 扣减库存(调用库存服务)
storagefeignclient.deduct(order.getproductid());
// 2. 创建订单(本地事务)
ordermapper.insert(order);
// 3. 模拟异常触发回滚
int i = 1 / 0;
}
}关键机制:
- 一阶段:提交本地事务,生成回滚日志(undo_log)
- 二阶段:成功则异步删除日志,失败则通过日志反向补偿
特点:
- 对代码无侵入
- 需创建undo_log表
- 适用于大多数crud场景
2.xa模式(强一致)
原理:基于数据库xa协议的两阶段提交
配置:
seata: data-source-proxy-mode: xa # 默认at
特点:
- 基于数据库xa协议
- 两阶段提交(2pc)
- 事务持有锁时间较长,适合短事务
适用场景:强一致性需求,支持xa协议的数据库(如mysql 5.7+)
3.tcc模式(手动补偿)
原理:try-confirm-cancel 三阶段控制
实现:
// 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. 实现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;
}
}使用限制:
- 需自行实现try/confirm/cancel方法
- confirm和cancel需保证幂等性
特点:高性能,但需手动编写补偿逻辑
4.saga模式(长事务)
实现方式:
通过状态机配置补偿策略:
@sagastart
public void createordersaga(order order) {
// 1. 创建订单
orderservice.create(order);
// 2. 调用支付服务(若失败则触发逆向操作)
paymentservice.pay(order.getid());
}
// 定义补偿方法
@compensate
public void compensateorder(order order) {
orderservice.delete(order.getid());
}原理:长事务拆分+逆向补偿
适用场景:跨系统长时间操作(如订单+物流+支付)
总结
模式选型对照表:
| 模式 | 一致性 | 性能 | 侵入性 | 适用场景 |
|---|---|---|---|---|
| at | 弱一致 | 高 | 低 | 常规业务(库存扣减、订单创建) |
| tcc | 强一致 | 中 | 高 | 资金交易、需精准控制 |
| xa | 强一致 | 低 | 低 | 银行转账、短事务 |
| saga | 最终一致 | 高 | 中 | 跨系统长流程(订单+物流+支付) |
核心要点:
| 分类 | 要点说明 |
|---|---|
| 选型 | at模式适用于大多数场景,tcc适合高性能要求,xa适合强一致性 |
| 配置 | 确保seata-server与微服务的registry配置一致 |
| 事务id | 通过rootcontext.getxid()可获取当前事务id |
| 排错 | 检查undo_log表记录,查看seata-server控制台日志 |
最佳实践:
- 生产环境建议使用nacos作为配置中心
- at模式需要开启数据库的本地事务支持(如mysql的innodb引擎)
- 全局事务超时时间建议设置:
seata.tx.timeout=60000(单位毫秒)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论