一、Seata 核心概念
解决微服务跨库调用分布式事务一致性问题,主流AT自动事务模式(无侵入,业务代码改动极小)。
三大角色
- TC 事务协调器:独立服务,全局事务管理者,记录全局锁、事务状态、触发提交/回滚;
- TM 事务管理器:发起全局事务(入口服务),加注解
@GlobalTransactional; - RM 资源管理器:每个参与事务的微服务,分支事务执行、上报状态、释放锁。
二、Windows 部署 Seata TC
可选 注册到Nacos
1. 下载解压
下载地址:官网
下载 seata-server 压缩包,解压路径无中文空格,示例D:\soft\seata-1.8.0。
2. 修改注册&配置文件 registry.conf
registry { type = "nacos" nacos { application = "seata-server" serverAddr = "127.0.0.1:8848" group = "DEFAULT_GROUP" namespace = "public" cluster = "default" } } config { type = "nacos" nacos { serverAddr = "127.0.0.1:8848" group = "DEFAULT_GROUP" namespace = "public" } }3. 修改 store.mode
存储模式
file.conf
store { mode = "db" # 生产用db,默认file重启事务数据丢失 db { datasource = "druid" druid { url = "jdbc:mysql://127.0.0.1:3306/seata_tc?useUnicode=true" user = "root" password = "你的密码" driverClassName = "com.mysql.cj.jdbc.Driver" } } }4. 初始化TC库表
新建库seata_tc,执行 seata 目录下script/server/db/mysql.sql建表。
5. 启动TC
cmd 进入 bin:
seata-server.batNacos 服务列表出现seata-server,TC注册成功。
三、每个参与分布式事务的业务库必须建undo_log表
每个微服务自己的业务库执行下面SQL:
CREATETABLE`undo_log`(`id`bigintNOTNULLAUTO_INCREMENT,`branch_id`bigintNOTNULL,`xid`varchar(128)NOTNULL,`context`varchar(128)NOTNULL,`rollback_info`longblobNOTNULL,`log_status`intNOTNULL,`log_created`datetimeNOTNULL,`log_modified`datetimeNOTNULL,PRIMARYKEY(`id`),UNIQUEKEY`ux_undo_log`(`xid`,`branch_id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;AT模式依靠undo_log生成回滚快照,必须每张业务库单独建。
四、微服务客户端接入
1. 依赖
所有参与分布式事务的微服务都引入:
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency>2. application.yml 统一配置
spring:cloud:alibaba:seata:tx-service-group:my_tx_group# 自定义事务组名nacos:discovery:server-addr:127.0.0.1:8848额外补充:在Nacos配置中心新建配置,Data IDseata.properties
service.vgroupMapping.my_tx_group=defaultmy_tx_group对应上面tx-service-group,default是TC集群名。
五、AT模式代码
场景举例
下单服务(order)→ 扣库存(stock)→ 扣余额(account)
任意下游抛出异常,所有库同时回滚。
1. 事务发起方(Order服务 TM)
全局事务注解@GlobalTransactional
@ServicepublicclassOrderServiceImplimplementsOrderService{@AutowiredprivateStockFeignClientstockFeignClient;@AutowiredprivateAccountFeignClientaccountFeignClient;@Override@GlobalTransactional(rollbackFor=Exception.class)// 开启全局事务publicvoidcreateOrder(LonguserId,LonggoodsId,Integernum){// 1. 新增订单insertOrder(userId,goodsId,num);// 2. 远程扣库存stockFeignClient.deduct(goodsId,num);// 3. 远程扣余额accountFeignClient.deduct(userId,num*100);// 模拟异常,触发全局回滚inti=1/0;}}2. 下游RM服务(Stock、Account)
普通本地事务@Transactional即可,不用加全局注解,Seata自动接管分支事务:
@ServicepublicclassStockServiceImplimplementsStockService{@Transactional@Overridepublicvoiddeduct(LonggoodsId,Integernum){// 扣减库存SQL}}六、测试效果
- 执行下单接口,代码抛出除零异常;
- 预期:订单插入、库存扣减、余额扣减全部自动回滚,三张表数据无变更;
- 去掉异常,全部正常提交,数据一致。
七、关键补充要点
1. AT模式原理
一阶段:执行业务SQL,记录undo_log,提交本地事务,释放锁;
二阶段正常:删除undo_log;
二阶段异常:根据undo_log自动反向补偿回滚。
2. Feign远程调用传递XID
新版starter自动拦截Feign请求,全局事务XID自动透传,无需手动拦截器处理。
3. 四种模式适用场景
- AT:无侵入,MySQL支持,绝大多数微服务首选;
- TCC:侵入高,自定义确认/取消接口,非关系型数据库用;
- SAGA:长事务、流程编排;
- XA:数据库原生两阶段,性能差,极少使用。
八、高频踩坑
- 忘记给每个业务库建undo_log:分支事务无法注册,事务失效;
- tx-service-group 和 Nacos 里 vgroupMapping 不匹配:找不到TC;
- 本地@Transactional 缺失:分支事务不会上报RM;
- TC用file存储,重启后未完成事务丢失:务必切换db存储;
- 多数据源场景:必须手动指定数据源代理,Seata才能接管。