zoukankan      html  css  js  c++  java
  • SEATA 分布式事务入门DEMO

    Simple Extensible Autonomous Transacation Architecture,seata是简单的、可扩展、自主性高的分布式架构

    SEATA Server Configure

    因我们使用正式的1.0.0-GA 版本,网上大多数找到的说明都是0.X版本,有不少变动,比如,在server中取消了db_store.sql的脚本,如找不到相关内容,可以通过源码来查找,比如db脚本源码:mysql db script

    1. 下载 seata-server

    2. 创建数据库(seata),可自定义,在file.conf中要用到。

      -- -------------------------------- The script used when storeMode is 'db' --------------------------------
      -- the table to store GlobalSession data
      CREATE TABLE IF NOT EXISTS `global_table`
      (
          `xid`                       VARCHAR(128) NOT NULL,
          `transaction_id`            BIGINT,
          `status`                    TINYINT      NOT NULL,
          `application_id`            VARCHAR(32),
          `transaction_service_group` VARCHAR(32),
          `transaction_name`          VARCHAR(128),
          `timeout`                   INT,
          `begin_time`                BIGINT,
          `application_data`          VARCHAR(2000),
          `gmt_create`                DATETIME,
          `gmt_modified`              DATETIME,
          PRIMARY KEY (`xid`),
          KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
          KEY `idx_transaction_id` (`transaction_id`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8;
      
      -- the table to store BranchSession data
      CREATE TABLE IF NOT EXISTS `branch_table`
      (
          `branch_id`         BIGINT       NOT NULL,
          `xid`               VARCHAR(128) NOT NULL,
          `transaction_id`    BIGINT,
          `resource_group_id` VARCHAR(32),
          `resource_id`       VARCHAR(256),
          `branch_type`       VARCHAR(8),
          `status`            TINYINT,
          `client_id`         VARCHAR(64),
          `application_data`  VARCHAR(2000),
          `gmt_create`        DATETIME,
          `gmt_modified`      DATETIME,
          PRIMARY KEY (`branch_id`),
          KEY `idx_xid` (`xid`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8;
      
      -- the table to store lock data
      CREATE TABLE IF NOT EXISTS `lock_table`
      (
          `row_key`        VARCHAR(128) NOT NULL,
          `xid`            VARCHAR(96),
          `transaction_id` BIGINT,
          `branch_id`      BIGINT       NOT NULL,
          `resource_id`    VARCHAR(256),
          `table_name`     VARCHAR(32),
          `pk`             VARCHAR(36),
          `gmt_create`     DATETIME,
          `gmt_modified`   DATETIME,
          PRIMARY KEY (`row_key`),
          KEY `idx_branch_id` (`branch_id`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8;
      
    3. 编辑file.conf配置文件

      service {
        #transaction service group mapping
        vgroup_mapping.sunrise_tx_group = "default"
        #only support when registry.type=file, please don't set multiple addresses
        default.grouplist = "127.0.0.1:8091"
        #disable seata
        disableGlobalTransaction = false
        #degrade current not support
        enableDegrade = false
        #disable
        disable = false
        #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
        max.commit.retry.timeout = "-1"
        max.rollback.retry.timeout = "-1"
      }
      
      ## transaction log store, only used in seata-server
      store {
        ## store mode: file、db
        mode = "db"
      
        ## file store property
        file {
          ## store location dir
          dir = "sessionStore"
        #degrade current not support
        enableDegrade = false
        #disable
        disable = false
        #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
        max.commit.retry.timeout = "-1"
        max.rollback.retry.timeout = "-1"
      }
      
      ## transaction log store, only used in seata-server
      store {
        ## store mode: file、db
        mode = "db"
      
        ## file store property
        file {
          ## store location dir
          dir = "sessionStore"
        }
      
        ## database store property
        db {
          ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
          datasource = "dbcp"
          ## mysql/oracle/h2/oceanbase etc.
          db-type = "mysql"
          driver-class-name = "com.mysql.jdbc.Driver"
          url = "jdbc:mysql://localhost:3306/seata"
          user = "wr"
          password = "wr"
          min-conn = 1
          max-conn = 3
          global.table = "global_table"
          branch.table = "branch_table"
          lock-table = "lock_table"
          query-limit = 100
        }
      }
      
    4. 编辑conf/regiester.conf

      registry {
        # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
        # 更改1
        type = "eureka"
      
        nacos {
          serverAddr = "localhost"
          namespace = ""
          cluster = "default"
        }
        eureka {
        	# 更改2
          serviceUrl = "http://localhost:21001/eureka"
          application = "default"
          weight = "1"
        }
        redis {
          serverAddr = "localhost:6379"
          db = "0"
        }
        zk {
          cluster = "default"
          serverAddr = "127.0.0.1:2181"
          session.timeout = 6000
          connect.timeout = 2000
        }
        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
        type = "file"
      
        nacos {
          serverAddr = "localhost"
          namespace = ""
        }
        consul {
          serverAddr = "127.0.0.1:8500"
        }
        apollo {
          app.id = "seata-server"
          apollo.meta = "http://192.168.1.204:8801"
        }
        zk {
          serverAddr = "127.0.0.1:2181"
          session.timeout = 6000
          connect.timeout = 2000
        }
        etcd3 {
          serverAddr = "http://localhost:2379"
        }
        file {
          name = "file.conf"
        }
      }
      

      本次实现,我们还没有添加configration的时候,因此只需要更改register块中的相关属性即可,在后续我们实现了nacos config之后,再同步更新这里。

    5. 启动服务端

      [root@localhost.localdomain /usr/local/geekplus/server/seata]# bin/seata-server.sh 
      

    eureka ha
    eureka中看到如下8091端口的服务之后,即启动seata-server正常!

    Client Configure

    AT Model

    需要在每一个业务库中添加数据表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;
    

    Broadway-Demo

    使用Springboot项目有一个小规律,我叫它为使用三部曲。
    broadway-ws-tally-service项目为例:

    • 第一步:加依赖

              <!--seata-->
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-alibaba-seata</artifactId>
                  <version>2.1.0.RELEASE</version>
                  <exclusions>
                      <exclusion>
                          <artifactId>seata-all</artifactId>
                          <groupId>io.seata</groupId>
                      </exclusion>
                  </exclusions>
              </dependency>
              <dependency>
                  <groupId>io.seata</groupId>
                  <artifactId>seata-all</artifactId>
                  <version>1.0.0</version>
              </dependency>
      
    • 第二步:开启注解

      @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
      

      在这里需要说明一下,我们需要排除掉SpringBoot默认自动注入的DataSourceAutoConfigurationBean, 因为SEATA是基于数据源拦截来实现的分布式事务,因此,我们需要自定义数据源配置信息:

      package com.geekplus.broadway.ws.tally.application;
      
      import com.alibaba.druid.pool.DruidDataSource;
      import io.seata.rm.datasource.DataSourceProxy;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.mybatis.spring.SqlSessionFactoryBean;
      import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
      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 {
          @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 sqlSessionFactoryBean = new SqlSessionFactoryBean();
              sqlSessionFactoryBean.setDataSource(dataSourceProxy);
              sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                      .getResources("classpath*:/com/geekplus/*.xml"));
              sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
              return sqlSessionFactoryBean.getObject();
          }
      }
      

      该配置类,一般放在与启动类相同的目录即可!

    • 第三部:改配置

      spring:
        cloud:
          alibaba:
            seata:
              tx-service-group: sunrise_tx_group 
      

      TIPS:
      tx-service-group 一定要server,client都要保持一致,否则能坑死你!
      tx-service-group 一定要server,client都要保持一致,否则能坑死你!
      tx-service-group 一定要server,client都要保持一致,否则能坑死你!

    以上三步是大多数SpringBoot 项目的通用做法,当然我们的SEATA暂时还不是那么完善,配置信息目前还不支持在application.yml中配置完全,因此,我们需要2个核心的client 配置文件file.confregister.conf.

    • file.conf 该文件主要是用于连接RM的,我们只需要关注上面所说的tx-service-group就行,其他配置默认就可以。

      transport {
        # tcp udt unix-domain-socket
        type = "TCP"
        #NIO NATIVE
        server = "NIO"
        #enable heartbeat
        heartbeat = true
        # the client batch send request enable
        enable-client-batch-send-request = true
        #thread factory for netty
        thread-factory {
          boss-thread-prefix = "NettyBoss"
          worker-thread-prefix = "NettyServerNIOWorker"
          server-executor-thread-prefix = "NettyServerBizHandler"
          share-boss-worker = false
          client-selector-thread-prefix = "NettyClientSelector"
          client-selector-thread-size = 1
          client-worker-thread-prefix = "NettyClientWorkerThread"
          # netty boss thread size,will not be used for UDT
          boss-thread-size = 1
          #auto default pin or 8
          worker-thread-size = 8
        }
        shutdown {
          # when destroy server, wait seconds
          wait = 3
        }
        serialization = "seata"
        compressor = "none"
      }
      
      service {
        #transaction service group mapping
        vgroup_mapping.sunrise_tx_group = "default"
        #only support when registry.type=file, please don't set multiple addresses
        default.grouplist = "127.0.0.1:8091"
        #disable seata
        disableGlobalTransaction = false
      }
      
      client {
        rm {
          async.commit.buffer.limit = 10000
          lock {
            retry.internal = 10
            retry.times = 30
            retry.policy.branch-rollback-on-conflict = true
          }
          report.retry.count = 5
          table.meta.check.enable = false
          report.success.enable = true
        }
        tm {
          commit.retry.count = 5
          rollback.retry.count = 5
        }
        undo {
          data.validation = true
          log.serialization = "jackson"
          log.table = "undo_log"
        }
        log {
          exceptionRate = 100
        }
        support {
          # auto proxy the DataSource bean
          spring.datasource.autoproxy = false
        }
       }
      
    • register.conf该文件是用于指定注册中心相关配置的,它有2个核心block

      • registry块
        此模板表明我们的注册中心使用类型,需要根据type设置来同步更新使用的配置信息,比如我们使用的eureka,因此我们更新eureka.serviceUrl="http://172.16.1.187:21001/eureka".

      • config 块
        该模块用来设置我们的配置中心相关配置(此处后续更新,我们会选择apollo

      registry {
        # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
        type = "eureka"
      
        nacos {
          serverAddr = "localhost"
          namespace = ""
          cluster = "default"
        }
        eureka {
          serviceUrl = "http://172.16.1.187:21001/eureka"
          application = "default"
          weight = "1"
        }
        redis {
          serverAddr = "localhost:6379"
          db = "0"
        }
        zk {
          cluster = "default"
          serverAddr = "127.0.0.1:2181"
          session.timeout = 6000
          connect.timeout = 2000
        }
        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
        type = "file"
      
        nacos {
          serverAddr = "localhost"
          namespace = ""
        }
        consul {
          serverAddr = "127.0.0.1:8500"
        }
        apollo {
          app.id = "seata-server"
          apollo.meta = "http://192.168.1.204:8801"
        }
        zk {
          serverAddr = "127.0.0.1:2181"
          session.timeout = 6000
          connect.timeout = 2000
        }
        etcd3 {
          serverAddr = "http://localhost:2379"
        }
        file {
          name = "file.conf"
        }
      }
      
  • 相关阅读:
    网络管理不得不知道的一些常识
    DWZ(一):框架初了解
    第三天 ThinkPHP手把手高速拼接站点(三)
    stl之list双向链表容器应用基础
    如何使用ninja编译系统编译我们的程序?
    由抓取豆瓣信息想到的網絡知識
    学习实践:使用模式,原则实现一个C++数据库訪问类
    加入新的linux系统调用
    【转】repo 的一些用法和理解-不错
    【转】ubuntu 12.04 LTS将关闭最大化最小化移动到右上角
  • 原文地址:https://www.cnblogs.com/zhangpan1244/p/12198147.html
Copyright © 2011-2022 走看看