-
使用seata来实现分布式事务是十分主流且简单的一种方式,首先就是先安装SeataServer
- 下载链接:https://github.com/seata/seata/tags
- 如果内存不够时会启动失败,可以修改配置文件解决
-
在微服务中集成seata
-
首先导入依赖
<!--seata依赖,TM+RM集成包--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency> <!--seata也需要连接数据库,进行undolog表的日志存储,所以需要用到连接池,我们已经导入过了--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency>
-
配置yml文件
seata: enableAutoDataSourceProxy: false #关闭DataSource代理的自动配置,我们要手动配置 spring: cloud: alibaba: seata: tx-service-group: fsp_tx_group #这里和file.conf中事务组名一样
-
在resources中进行配置(resources/file.conf)
transport { # tcp udt unix-domain-socket type = "TCP" #NIO NATIVE server = "NIO" #enable heartbeat heartbeat = true # the client batch send request enable enableClientBatchSendRequest = true #thread factory for netty threadFactory { bossThreadPrefix = "NettyBoss" workerThreadPrefix = "NettyServerNIOWorker" serverExecutorThread-prefix = "NettyServerBizHandler" shareBossWorker = false clientSelectorThreadPrefix = "NettyClientSelector" clientSelectorThreadSize = 1 clientWorkerThreadPrefix = "NettyClientWorkerThread" # netty boss thread size,will not be used for UDT 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.fsp_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 reportSuccessEnable = false } tm { commitRetryCount = 5 rollbackRetryCount = 5 } undo { dataValidation = true logSerialization = "jackson" logTable = "undo_log" } log { exceptionRate = 100 } }
-
resources/registry.conf
registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "file" nacos { serverAddr = "localhost" namespace = "" cluster = "default" } eureka { serviceUrl = "http://localhost:8761/eureka" application = "default" weight = "1" } redis { serverAddr = "localhost:6379" db = "0" password = "" cluster = "default" timeout = "0" } zk { cluster = "default" serverAddr = "127.0.0.1:2181" session.timeout = 6000 connect.timeout = 2000 username = "" password = "" } consul { cluster = "default" serverAddr = "127.0.0.1:8500" } etcd3 { cluster = "default" serverAddr = "http://localhost:2379" } sofa { serverAddr = "127.0.0.1:9603" application = "default" region = "DEFAULT_ZONE" datacenter = "DefaultDataCenter" cluster = "default" group = "SEATA_GROUP" addressWaitTime = "3000" } file { name = "file.conf" } } config { # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig type = "file" nacos { serverAddr = "localhost" namespace = "" group = "SEATA_GROUP" } consul { serverAddr = "127.0.0.1:8500" } apollo { app.id = "seata-server" apollo.meta = "http://192.168.1.204:8801" namespace = "application" } zk { serverAddr = "127.0.0.1:2181" session.timeout = 6000 connect.timeout = 2000 username = "" password = "" } etcd3 { serverAddr = "http://localhost:2379" } file { name = "file.conf" } }
-
DataSource配置
-
在启动类注解上排除DataSource自动配置:@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})
-
MybatisPlus版本:把DataSource交给Seata代理
package com.zcy.jkcc.config; import com.alibaba.druid.pool.DruidDataSource; import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; import io.seata.rm.datasource.DataSourceProxy; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import javax.sql.DataSource; /** * 数据源代理 */ @Configuration public class DataSourceConfiguration { //mapper.xml路径 @Value("${mybatis-plus.mapper-locations}") private String mapperLocations; //手动配置bean @Bean @ConfigurationProperties("spring.datasource") public DataSource druidDataSource(){ return new DruidDataSource(); } @Bean public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception { //处理MybatisPlus MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSourceProxy); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); //事务管理工厂 factory.setTransactionFactory(new SpringManagedTransactionFactory()); return factory; } @Primary @Bean("dataSource") public DataSourceProxy dataSourceProxy(DataSource druidDataSource) { return new DataSourceProxy(druidDataSource); } }
-
Mybatis版本:把DataSource交给Seata代理
package cn.itsource.ymcc.config; import com.alibaba.druid.pool.DruidDataSource; import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; import io.seata.rm.datasource.DataSourceProxy; import org.mybatis.spring.transaction.SpringManagedTransactionFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import javax.sql.DataSource; /** * 数据源代理 */ @Configuration public class DataSourceConfiguration { //mapper.xml路径 @Value("${mybatis-plus.mapper-locations}") private String mapperLocations; //手动配置bean @Bean @ConfigurationProperties("spring.datasource") public DataSource druidDataSource(){ return new DruidDataSource(); } @Bean public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception { //处理MybatisPlus MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSourceProxy); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations)); //事务管理工厂 factory.setTransactionFactory(new SpringManagedTransactionFactory()); return factory; } @Primary @Bean("dataSource") public DataSourceProxy dataSourceProxy(DataSource druidDataSource) { return new DataSourceProxy(druidDataSource); } }
-
-
在需要开启全局事务的方法上面加上注解:@GlobalTransactional(rollbackFor = Exception.class) 开启Seata全局事务
-
注释掉事务开启注解:
注意:MybatisPlusConfig中的@EnableTransactionManagement注解不能加, 也不需要加@Transactional注解
-
然后在涉及到事务的表中都需要添加undolog表:
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log 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;
-
最后在事务参与方也编写和主业务方一致的配置,但是不用加@GlobalTransactional(rollbackFor = Exception.class) 注解
-
测试
-
系统中使用seata实现分布式事务的步骤
最新推荐文章于 2024-02-24 11:29:20 发布