1. Seata与分布式事务概述
在微服务架构中,随着业务复杂度的提升,一个业务操作往往需要跨多个服务完成。这就带来了分布式事务的挑战——如何保证跨服务的数据一致性。传统单机事务的ACID特性在分布式环境下难以直接应用,Seata应运而生。
Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。它支持AT、TCC、Saga和XA四种事务模式,能够满足不同业务场景的需求。
提示:在微服务架构中,数据库被拆分到不同服务中,传统的本地事务无法保证跨服务的数据一致性,这就是分布式事务要解决的问题。
2. Seata核心架构与工作原理
2.1 Seata的三大角色
Seata的架构中包含三个核心角色:
-
TC (Transaction Coordinator) - 事务协调者:
- 维护全局和分支事务的状态
- 驱动全局事务提交或回滚
- 独立部署的Server端
-
TM (Transaction Manager) - 事务管理器:
- 定义全局事务的范围
- 开始全局事务、提交或回滚全局事务
- 嵌入到应用中的Client端
-
RM (Resource Manager) - 资源管理器:
- 管理分支事务处理的资源
- 与TC交谈以注册分支事务和报告分支事务状态
- 驱动分支事务提交或回滚
- 嵌入到应用中的Client端
2.2 分布式事务生命周期
一个典型的Seata分布式事务生命周期如下:
- TM向TC申请开始一个全局事务,TC生成XID作为该全局事务的编号
- XID在微服务调用链中传播,确保多个微服务的子事务关联在一起
- RM向TC注册本地事务为全局事务的分支事务,通过XID进行关联
- TM向TC告知XID对应的全局事务是进行提交还是回滚
- TC驱动RMs将XID对应的自己的本地事务进行提交或回滚
2.3 Seata支持的事务模式
Seata提供四种事务模式以适应不同场景:
-
AT模式(自动补偿型):
- 基于本地ACID事务实现
- 通过全局锁保证隔离性
- 无业务侵入,使用简单
-
TCC模式(手动补偿型):
- 需要业务实现Try、Confirm、Cancel接口
- 性能较好,但业务侵入性强
- 适用于对性能要求高且能接受改造的业务
-
Saga模式:
- 长事务解决方案
- 每个参与者都实现正向操作和补偿操作
- 适用于业务流程长且需要最终一致性的场景
-
XA模式:
- 基于数据库XA协议实现
- 强一致性,但性能较差
- 适用于传统XA场景
3. Seata与Spring Cloud集成实战
3.1 环境准备
在Spring Cloud项目中集成Seata需要以下组件:
- Seata Server(TC)1.5.0+
- Spring Boot 2.3.x+
- Spring Cloud Hoxton.SR12+
- Spring Cloud Alibaba 2.2.6.RELEASE+
Maven依赖配置:
xml复制<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.5.0</version>
</dependency>
3.2 配置Seata Client
在application.yml中添加Seata配置:
yaml复制seata:
application-id: ${spring.application.name}
tx-service-group: my_tx_group
service:
vgroup-mapping:
my_tx_group: default
grouplist:
default: 127.0.0.1:8091
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
cluster: default
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
3.3 数据源代理配置
Seata AT模式需要通过代理数据源来实现事务控制:
java复制@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource druidDataSource() {
return new DruidDataSource();
}
@Primary
@Bean("dataSource")
public DataSource dataSource(DruidDataSource druidDataSource) {
return new DataSourceProxy(druidDataSource);
}
}
3.4 全局事务使用示例
在业务方法上添加@GlobalTransactional注解即可开启全局事务:
java复制@Service
public class OrderServiceImpl implements OrderService {
@GlobalTransactional(name = "createOrder", rollbackFor = Exception.class)
public void createOrder(Order order) {
// 1. 创建订单
orderMapper.insert(order);
// 2. 扣减库存(调用库存服务)
storageFeignClient.deduct(order.getCommodityCode(), order.getCount());
// 3. 扣减余额(调用账户服务)
accountFeignClient.debit(order.getUserId(), order.getMoney());
}
}
4. Seata AT模式深度解析
4.1 AT模式工作原理
AT模式是Seata最常用的模式,其工作流程分为两个阶段:
-
第一阶段:
- 执行业务SQL,保存"before image"(前置镜像)
- 执行业务SQL
- 保存"after image"(后置镜像)
- 生成undo log记录
- 向TC注册分支事务
-
第二阶段:
- 如果全局事务成功:异步删除undo log
- 如果全局事务失败:根据undo log生成反向SQL进行补偿
4.2 全局锁机制
AT模式通过全局锁保证隔离性,关键点包括:
- 在业务表操作前获取全局锁
- 如果获取不到锁则重试或回滚
- 全局锁由TC统一管理
- 默认获取锁超时时间为30秒
4.3 undo_log表设计
AT模式需要在每个业务数据库中创建undo_log表:
sql复制CREATE TABLE `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,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
5. 生产环境部署最佳实践
5.1 Seata Server高可用部署
生产环境建议采用集群部署:
-
存储模式选择:
- 使用db模式而非file模式
- 配置共享数据库(MySQL集群)
-
注册中心配置:
- 使用Nacos作为注册中心
- 多个Seata Server实例注册到同一集群
-
配置中心:
- 使用Nacos作为配置中心
- 统一管理所有Seata配置
5.2 性能优化建议
-
TC Server参数调优:
properties复制# 工作线程数 server.workerThreads=500 # 业务执行线程池大小 server.businessThreads=1000 -
客户端参数优化:
yaml复制seata: client: rm: report-retry-count: 5 async-commit-buffer-limit: 10000 tm: commit-retry-count: 5 rollback-retry-count: 5 -
数据库优化:
- undo_log表添加合适索引
- 定期清理已完成的undo log
5.3 监控与运维
-
Metrics监控:
- 集成Prometheus监控
- 配置Grafana监控面板
-
日志配置:
- 合理设置日志级别
- 日志文件滚动策略
-
告警机制:
- 事务失败告警
- 全局锁竞争告警
6. 常见问题与解决方案
6.1 全局锁冲突
现象:出现"Global lock wait timeout"错误
解决方案:
- 优化业务逻辑,减少事务时长
- 调整锁等待超时时间
- 考虑使用TCC模式替代AT模式
6.2 事务悬挂
现象:分支事务已提交但全局事务回滚
预防措施:
- 确保TM的@GlobalTransactional注解正确配置rollbackFor
- 避免在事务方法中捕获异常不抛出
6.3 幂等控制
问题:网络异常导致重复提交
解决方案:
- 业务层实现幂等控制
- 利用Seata的xid作为幂等键
6.4 跨服务调用问题
问题:Feign调用时xid未传播
解决方案:
- 确保正确配置Seata的Feign拦截器
- 检查服务间调用是否经过网关,确保header透传
在实际项目中使用Seata时,建议从测试环境开始逐步验证,确保充分理解其工作机制后再上生产。对于关键业务系统,建议配合完善的监控和告警机制,确保能够及时发现和处理分布式事务问题。
