系统中使用seata实现分布式事务的步骤

  1. 使用seata来实现分布式事务是十分主流且简单的一种方式,首先就是先安装SeataServer

    1. 下载链接:https://github.com/seata/seata/tags
    2. 如果内存不够时会启动失败,可以修改配置文件解决
  2. 在微服务中集成seata

    1. 首先导入依赖

              <!--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>
      
    2. 配置yml文件

      seata:
        enableAutoDataSourceProxy: false #关闭DataSource代理的自动配置,我们要手动配置
      spring:
        cloud:
          alibaba:
            seata:
              tx-service-group: fsp_tx_group #这里和file.conf中事务组名一样  
      
    3. 在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
        }
      }
      
      
    4. 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"
        }
      }
      
      
    5. DataSource配置

      1. 在启动类注解上排除DataSource自动配置:@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})

      2. 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);
            }
        
        }
        
        
      3. 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);
            }
        
        }
        
    6. 在需要开启全局事务的方法上面加上注解:@GlobalTransactional(rollbackFor = Exception.class) 开启Seata全局事务

    7. 注释掉事务开启注解:

      注意:MybatisPlusConfig中的@EnableTransactionManagement注解不能加, 也不需要加@Transactional注解

    8. 然后在涉及到事务的表中都需要添加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;
      
    9. 最后在事务参与方也编写和主业务方一致的配置,但是不用加@GlobalTransactional(rollbackFor = Exception.class) 注解

    10. 测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值