springCloud 整合seata实现分布式事务

一. 为何需要使用分布式事务?

针对跨服务,需要保证事务的业务,特引入阿里的分布式事务seata来解决问题。

二. 开始

1. 注册seata-server至eureka

我这里选择1.3.0版本
1)首先下载服务端源码,链接https://github.com/seata/seata/tree/1.3.0,找到server作为springcloud的seata服务端源码。
springCloud 整合seata实现分布式事务_第1张图片
springCloud 整合seata实现分布式事务_第2张图片
2)配置

##注册中心
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  # 注册类型,项目框架为springcloud ,这里使用eureka注册方式
  type = "eureka"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
# eureka 配置
  eureka {
    # 您的eureka地址
    serviceUrl = "http://127.0.0.1:8761/eureka"
    # seata服务端注册到eureka的实例应用名称
    application = "service-seata-server"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
    aclToken = ""
  }
  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
  # 本地配置(读本地文件, 包含conf、properties、yml配置文件的支持)
  type = "file"

  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
    dataId = "seataServer.properties"
  }
  consul {
    serverAddr = "127.0.0.1:8500"
    aclToken = ""
  }
  apollo {
    appId = "seata-server"
    ## apolloConfigService will cover apolloMeta
    apolloMeta = "http://192.168.1.204:8801"
    apolloConfigService = "http://192.168.1.204:8080"
    namespace = "application"
    apolloAccesskeySecret = ""
    cluster = "seata"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
    nodePath = "/seata/seata.properties"
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    ## 根据不同环境配置不同的配置
    name = "file-dev.conf"
  }
}

## 配置中心
## transaction log store, only used in seata-server
store {
  ## store mode: file、db、redis
  ## 存储模式 使用数据库存储事务日志
  mode = "db"
  ## rsa decryption public key
  publicKey = ""
  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "hikari"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
    url = "jdbc:mysql://localhost:3306/seata?autoReconnect=true&characterEncoding=utf-8"
    user = "username"
    password = "password"
    minConn = 5
    maxConn = 100
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  ## redis store property
  redis {
    ## redis mode: single、sentinel
    mode = "single"
    ## single mode property
    single {
      host = "127.0.0.1"
      port = "6379"
    }
    ## sentinel mode property
    sentinel {
      masterName = ""
      ## such as "10.28.235.65:26379,10.28.235.65:26380,10.28.235.65:26381"
      sentinelHosts = ""
    }
    password = ""
    database = "0"
    minConn = 1
    maxConn = 10
    maxTotal = 100
    queryLimit = 100
  }
}

3)创建seata数据库,及对应表

CREATE TABLE `global_table` (
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) DEFAULT NULL,
  `transaction_service_group` varchar(32) DEFAULT NULL,
  `transaction_name` varchar(128) DEFAULT NULL,
  `timeout` int(11) DEFAULT NULL,
  `begin_time` bigint(20) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xid`),
  KEY `idx_gmt_modified_status` (`gmt_modified`,`status`),
  KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `branch_table` (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `resource_group_id` varchar(32) DEFAULT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `branch_type` varchar(8) DEFAULT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `client_id` varchar(64) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime(6) DEFAULT NULL,
  `gmt_modified` datetime(6) DEFAULT NULL,
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `lock_table` (
  `row_key` varchar(255) NOT NULL,
  `xid` varchar(128) DEFAULT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `table_name` varchar(32) DEFAULT NULL,
  `pk` varchar(36) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`row_key`),
  KEY `idx_branch_id` (`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4)最后发布seata-server服务

2. 客户端seata-client配置

1)pom.xml引入依赖

 <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-seata</artifactId>
            <version>2.2.0.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.3.0</version>
        </dependency>

2)application.properties配置

#seata config
#开启seata
seata.enabled=true
seata.excludes-for-auto-proxying=firstClassNameForExclude,secondClassNameForExclude
#项目实例应用名称
seata.application-id=${spring.application.name}
#是否开启数据源自动代理
seata.enable-auto-data-source-proxy=true
#是否使用JDK代理作为数据源自动代理的实现方式
seata.use-jdk-proxy=false
#异步提交缓存队列长度 默认10000。 二阶段提交成功,RM异步清理undo队列
seata.client.rm.async-commit-buffer-limit=1000
#一阶段结果上报TC重试次数	默认5次
seata.client.rm.report-retry-count=5
#自动刷新缓存中的表结构	默认false !!!默认值在参与事务的表中新增字段时会出现异常
seata.client.rm.table-meta-check-enable=true
#是否上报一阶段成功	truefalse,从1.1.0版本开始,默认false.true用于保持分支事务生命周期记录完整,false可提高不少性能
seata.client.rm.report-success-enable=false
seata.client.rm.saga-branch-register-enable=false
#校验或占用全局锁重试间隔	默认10,单位毫秒
seata.client.rm.lock.retry-interval=10
#校验或占用全局锁重试次数	默认30
seata.client.rm.lock.retry-times=30
#分支事务与其它全局回滚事务冲突时锁策略	默认true,优先释放本地锁让回滚成功
seata.client.rm.lock.retry-policy-branch-rollback-on-conflict=true
#一阶段全局提交结果上报TC重试次数	默认1次,建议大于1
seata.client.tm.commit-retry-count=5
#一阶段全局回滚结果上报TC重试次数	默认1次,建议大于1
seata.client.tm.rollback-retry-count=5
#降级开关	默认false。业务侧根据连续错误数自动降级不走seata事务(详细介绍请阅读附录6)
seata.client.tm.degrade-check=false
#升降级达标阈值	默认10
seata.client.tm.degrade-check-allow-times=10
#服务自检周期	默认2000,单位ms.2秒进行一次服务自检,来决定
seata.client.tm.degrade-check-period=2000
#二阶段回滚镜像校验	默认true开启,false关闭
seata.client.undo.data-validation=true
#undo序列化方式	默认jackson
seata.client.undo.log-serialization=jackson
seata.client.undo.only-care-update-columns=true
#自定义undo表名	默认undo_log
seata.client.undo.log-table=undo_log
#日志异常输出概率	默认100,目前用于undo回滚失败时异常堆栈输出,百分之一的概率输出,回滚失败基本是脏数据,无需输出堆栈占用硬盘空间
seata.client.log.exceptionRate=100
#事务群组(附录1)	my_test_tx_group为分组,配置项值为TC集群名
seata.tx-service-group=kcsm_tx_group
#TC服务列表(附录2)	仅注册中心为file时使用
seata.service.vgroup-mapping.kcsm_tx_group=service-seata-server
#seata.service.grouplist.default=127.0.0.1:8091
seata.service.enable-degrade=false
#全局事务开关	默认falsefalse为开启,true为关闭
seata.service.disable-global-transaction=false
seata.transport.shutdown.wait=3
seata.transport.thread-factory.boss-thread-prefix=NettyBoss
seata.transport.thread-factory.worker-thread-prefix=NettyServerNIOWorker
seata.transport.thread-factory.server-executor-thread-prefix=NettyServerBizHandler
seata.transport.thread-factory.share-boss-worker=false
seata.transport.thread-factory.client-selector-thread-prefix=NettyClientSelector
seata.transport.thread-factory.client-selector-thread-size=1
seata.transport.thread-factory.client-worker-thread-prefix=NettyClientWorkerThread
seata.transport.thread-factory.worker-thread-size=default
seata.transport.thread-factory.boss-thread-size=1
seata.transport.type=TCP
seata.transport.server=NIO
seata.transport.heartbeat=true
#client和server通信编解码方式	seata(ByteBuf)、protobuf、kryo、hession、fst,默认seata
seata.transport.serialization=seata
#client和server通信数据压缩方式	none、gzip,默认none
seata.transport.compressor=none
#客户端事务消息请求是否批量合并发送	默认truefalse单条发送
seata.transport.enable-client-batch-send-request=true
#配置中心类型	默认file,支持file、nacos 、apollo、zk、consul、etcd3、custom
seata.config.type=file
seata.registry.type=eureka
seata.registry.eureka.weight=1
#注册中心地址
seata.registry.eureka.service-url=localhost:8761/eureka
#日志级别
logging.level.org.springframework.cloud.alibaba.seata.web=info
logging.level.io.seata=info

3)客户端创建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,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

3. 应用

service方法上加入注解 @GlobalTransactional(rollbackFor = Exception.class)

三 结语

目前已应用生产,记录下用法,有什么问题请指正。
详细请参照官网:https://seata.io/zh-cn/docs/user/quickstart.html

你可能感兴趣的:(spring,cloud,分布式,java)