Eureka+Mybatis+Mysql 集成分布式事务Seata篇
初识Seata
Seata 是阿里巴巴开源的分布式事务中间件,一种分布式事务解决方案,具有高性能和易于使用的微服务架构。并致力于打造对业务无侵入:即减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入与高性能:减少分布式事务解决方案所带来的性能消耗等问题。
快速集成(AT)
AT 模式基于 支持本地 ACID 事务 的 关系型数据库:
一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。
前提:
seata目前是要求表必须有主键、并且不支持数据库表多主键
Maven配置
添加Spring Cloud Alibaba 依赖管理工具和 Seata 依赖
<!--Alibaba-seata 2.1.0RELEASE -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
查询其子依赖中seata-all的版本,修改为需要的版本
<!--Seata-all 0.8.0 -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>0.8.0</version>
</dependency>
添加配置文件
registry.conf
该配置用于指定 TC 的注册中心和配置文件,默认都是 file; 如果使用其他的注册中心,要求 Seata-Server 也注册到该配置中心
file.conf
该配置用于指定TC的相关属性;如果使用注册中心也可以将配置添加到配置中心
要注意的是 service.vgroup_mapping这个配置,在 Spring Cloud 中默认是${spring.application.name}-fescar-service-group,可以通过指定application.properties的 spring.cloud.alibaba.seata.tx-service-group这个属性覆盖,但是必须要和 file.conf 中的一致,否则会提示 no available server to connect
注入数据源
Seata 通过代理数据源的方式实现分支事务;MyBatis 和 JPA 都需要注入 io.seata.rm.datasource.DataSourceProxy, 不同的是,MyBatis 还需要额外注入 org.apache.ibatis.session.SqlSessionFactory。
@Bean
@ConfigurationProperties(prefix = “spring.datasource”)
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Primary
@Bean(“dataSource”)
public DataSourceProxy dataSource(DataSource druidDataSource) {
return new DataSourceProxy(druidDataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSourceProxy);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(“classpath*:/mapper/*.xml”));
factoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return factoryBean.getObject();
}
添加undo_log表
在业务相关的数据库中添加 undo_log 表,用于保存需要回滚的数据
CREATE TABLE undo_log
(
id
BIGINT(20) NOT NULL AUTO_INCREMENT, – 主键
branch_id
BIGINT(20) NOT NULL, – 分支事务ID
xid
VARCHAR(100) NOT NULL, – 全局事务ID
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
启动Seata-Server
在 https://github.com/seata/seata/releases 下载相应版本的 Seata-Server,修改 registry.conf为相应的配置(如果使用 file 则不需要修改),解压并通过以下命令启动:
sh ./bin/seata-server.sh
使用@GlobalTransactional开启事务
在业务的发起方的方法上使用@GlobalTransactional开启全局事务,Seata 会将事务的 xid 通过拦截器添加到调用其他服务的请求中,实现分布式事务
问题解析
因Seata官网还未出具体文档介绍,对于大多新上手的程序猿可能都会遇到不同的问题,然鹅网上也搜不到,因此自己总结了一些关于Seata的一些问题,希望能帮到大家,后期也会持续维护。
异常类
- threw exception; nested exception is io.seata.common.exception.NotSupportYetException: not support register type: null
答:一般都是配置有异常, 检查一下registry的type属性 - Cause:java.sql.SQLException:java.sql.SQLSyntaxErrorException:Unknow colwmn ‘context’ in ‘field’ list’
答:查看你的回滚日志表undo_log,0.7版本之后需要加上’ contxt’字段