seata开发指南

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: seata开发指南

一、介绍

​ Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 ATTCCSAGAXA 事务模式,为用户打造一站式的分布式解决方案。点击进入官网

1、整体机制

​ seata的整体机制由两阶段提交演变而来

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 全局事务提交:异步化。
    • 全局事务回滚:通过一阶段的回滚日志进行反向补偿。

2、原理

​ seata通过默认配置seata.enable-auto-data-source-proxy: true对数据源进行代理,当程序需要对数据库进行写操作时,seata可对要执行的sql语句进行分析获得该行数据的详细信息并保存在当前服务所连接的数据库的undo_log表中作为日志备份,当下游服务出现异常时,seata-server可以对上游服务的undo_log表中的数据进行回滚,以实现分布式事务的强一致性。

3、写隔离

  • 一阶段本地事务提交前,需要确保先拿到 全局锁
  • 拿不到 全局锁 ,不能提交本地事务。
  • 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。

4、读隔离

在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted)

如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT ... FOR UPDATE 语句的代理。

5、AT模式

前提

  • 基于支持本地 ACID 事务的关系型数据库。
  • Java 应用,通过 JDBC 访问数据库。

原理

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
  • 二阶段 commit 行为:马上成功结束,自动 异步批量清理回滚日志。
  • 二阶段 rollback 行为:通过回滚日志,自动 生成补偿操作,完成数据回滚。

应用

​ 适合支持事务的关系型数据库,如使用innodb的mysql数据库

6、TCC 模式

​ 所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

​ 该模式不依赖于数据库的事务支持。

原理

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

应用

​ 适合不支持事务的关系型数据库,如使用myisam的mysql数据库

7、Saga模式

​ Saga模式是SEATA提供的长事务解决方案。

​ 在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者。

​ 一阶段正向服务和二阶段补偿服务都由业务开发实现。

应用

  • 业务流程长、业务流程多
  • 参与者包含其它公司或遗留系统服务,无法提供 TCC 模式要求的三个接口

优点

  • 一阶段提交本地事务,无锁,高性能
  • 事件驱动架构,参与者可异步执行,高吞吐
  • 补偿服务易于实现

缺点

  • 不保证隔离性

​ 综上所述,本项目使用AT模式。

二、配置中心

​ 本项目使用nacos作为seata的配置中心,在nacos添加配置文件名为seata-server.properties,配置内容参考具体配置

#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none

#Transaction routing rules configuration, only for the client
# 注意:该配置为map类型,key为my_test_tx_group,value为seata-cluster
# 该配置与seata-server和seata-client严格要求一致
service.vgroupMapping.my_test_tx_group=seata-cluster
#If you use a registry, you can ignore it
#service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false

#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=seata_undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k

#Log rule configuration, for client and server
log.exceptionRate=100

#Transaction storage configuration, only for the server. The file, DB, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://ip:port/my_db?rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false
store.db.user=username
store.db.password=password
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=seata_global_table
store.db.branchTable=seata_branch_table
store.db.distributedLockTable=seata_distributed_lock
store.db.queryLimit=100
store.db.lockTable=seata_lock_table
store.db.maxWait=5000

#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.recovery.handleAllSessionPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false

#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

#security configuration, only for the server
security.secretKey = SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
security.tokenValidityInMilliseconds = 1800000   
security.ignore.urls = /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

三、注册中心

​ 本项目使用nacos作为seata的注册中心,通过nacos提供的服务发现,以实现seata在服务调用过程中对全局事务标识(xid)的传递。

二、安装seata-server(docker)

1、拉取镜像

docker pull seataio/seata-server:1.5.2

2、创建容器

docker run \
--name seata-server \
-d \
-p 8091:8091 \
-p 7091:7091 \
--restart=always \
seataio/seata-server:1.5.2

3、建表(仅db)

要求配置中心配置store.mode=db,并修改数据源等配置信息。

全局事务会话信息由3块内容构成,全局事务-->分支事务-->全局锁,对应表global_table、branch_table、lock_table

建表DDL语句可查看官方文件

4、使用自定义配置文件

通过挂载文件的方式实现,将宿主机上的 application.yml 挂载到容器中相应的目录

docker cp seata-server:/seata-server/resources /data/seata/config

拷出后可以选择

    - 修改`application.yml`再`cp`进容器
    - `rm`临时容器,重新创建,并做好映射路径设置
docker run \
--name seata-server \
-d \
-p 8091:8091 \
-p 7091:7091 \
-v /data/seata/config/resources:/seata-server/resources \
--restart=always \
seataio/seata-server:1.5.2

5、环境变量

  • SEATA_IP

可选, 指定seata-server启动的IP, 该IP用于向注册中心注册时使用, 如eureka等

  • SEATA_PORT

可选, 指定seata-server启动的端口, 默认为 `8091

  • SERVER_NODE

可选, 用于指定seata-server节点ID, 如 1,2,3..., 默认为 根据ip生成

  • SEATA_ENV

可选, 指定 seata-server 运行环境, 如 dev, test 等, 服务启动时会使用 registry-dev.conf 这样的配置

6、修改配置文件

seata-server可配置的属性参考application.example.yaml

server:
  2   port: 7091
  3 spring:
  4   application:
  5     name: seata-server
  6   profiles:
  7     active: test
  8 
  9 logging:
 10   config: classpath:logback-spring.xml
 11   file:
 12     path: ${
   user.home}/logs/seata
 13   extend:
 14     logstash-appender:
 15       destination: 127.0.0.1:4560
 16     kafka-appender:
 17       bootstrap-servers: 127.0.0.1:9092
 18       topic: logback_to_logstash

 19 # seata控制台
 20 console:
 21   user:
 22     username: seata
 23     password: seata
 24 
 25 seata:
 26   config:
 27     # support: nacos, consul, apollo, zk, etcd3
         # 以nacos作为配置中心
 28     type: nacos
 29     nacos:
 30       server-addr: ip:port
 31       namespace: ${
   spring.profiles.active}
 32       group: SEATA_GROUP
 33       username: nacos
 34       password: nacos
 35       ##if use MSE Nacos with auth, mutex with username/password attribute
 36       #access-key: ""
 37       #secret-key: ""
 38       data-id: seata-server-dev.properties
 39   registry:
 40     # support: nacos, eureka, redis, zk, consul, etcd3, sofa
         # 以nacos作为服务注册中心
 41     type: nacos
 42     nacos:
 43       application: seata-server
 44       server-addr: ip:port
 45       group : SEATA_GROUP
 46       namespace: ${
   spring.profiles.active}
 47       username: nacos
 48       password: nacos
           # 该配置若不写,则默认为default
           # 注意:该配置与seata-client端的配置要求一致
          # 参考配置中心配置:service.vgroupMapping.my_test_tx_group=seata-cluster
 49       cluster: seata-cluster
 52   server:
 53     service-port: 8091 #If not configured, the default is '${server.port} + 1000'
 54     enable-check-auth: true
 55     retry-dead-threshold: 130000
6       undo:
 57       log-save-days: 7
 58       log-delete-period: 86400000

三、安装seata-client

1、pom依赖

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>最新版</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>最新版本</version>
    <exclusions>
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2、bootstrap.yaml添加配置

seata:
  application-id: ${
   spring.application.name}
  # 参考配置中心配置:service.vgroupMapping.my_test_tx_group=seata-cluster
  tx-service-group: my_test_tx_group
  config:
    type: nacos
    nacos:
      namespace: ${
   spring.profiles.active}
      data-id: seata-server-${
   spring.profiles.active}.properties
      server-addr: ${
   spring.cloud.nacos.discovery.server-addr}
      group: SEATA_GROUP
      username: ${
   spring.cloud.nacos.discovery.username}
      password: ${
   spring.cloud.nacos.discovery.password}
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: ${
   spring.cloud.nacos.discovery.server-addr}
      group: SEATA_GROUP
      namespace: ${
   spring.profiles.active}
      username: ${
   spring.cloud.nacos.discovery.username}
      password: ${
   spring.cloud.nacos.discovery.password}
  # 参考配置中心配置:service.vgroupMapping.my_test_tx_group=seata-cluster
  # 参考seata-server配置:seata.registry.nacos.cluster = seata-cluster
      cluster: seata-cluster

3、seata-AT模式需要建表

​ SEATA AT 模式需要 UNDO_LOG

-- 注意此处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;

四、Q&A

1、项目启动时seata报error日志

​ Q:启动时一直报错:

​ can not get cluster name in registry config 'service.vgroupMapping.default_tx_group', please make sure registry config correct

​ A:请检查

                - 配置中心是否配置了`service.vgroupMapping`属性,如果没配,则默认为`default_tx_group`
                - client端的`seata.tx-service-group`的值是否和配置中心`service.vgroupMapping`的key一致
                - client端的`seata.registry.nacos.cluster`的值是否和配置中心`service.vgroupMapping`的value一致
                - server端的`seata.registry.nacos.cluster`的值是否和配置中心`service.vgroupMapping`的value一致
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
关系型数据库 Java Nacos
Seata的部署和集成
部署Seata的tc-server
|
NoSQL Java Redis
【Seata】分布式事务框架Seata踩坑集锦
【Seata】分布式事务框架Seata踩坑集锦
【Seata】分布式事务框架Seata踩坑集锦
|
6月前
|
SQL 容灾 数据库
Seata笔记2
Seata笔记2
37 1
|
容灾 Shell Nacos
【Seata】seata的部署和集成
一、部署Seata的tc-server 1.下载 首先我们要下载seata-server包,地址在http://seata.io/zh-cn/blog/download.html
231 0
|
6月前
|
关系型数据库 MySQL Apache
|
6月前
|
SQL FESCAR 数据库
SpringCloud之Seata基本介绍与安装
SpringCloud之Seata基本介绍与安装
|
SQL 缓存 搜索推荐
分布式事务简介(seata)
分布式事务简介(seata)
206 0
|
Java 中间件 uml
阿里中间件seata源码剖析三:聊聊seata中的ShutdownHook
阿里中间件seata源码剖析三:聊聊seata中的ShutdownHook
275 7
阿里中间件seata源码剖析三:聊聊seata中的ShutdownHook
|
存储 SQL SpringCloudAlibaba
十一.SpringCloudAlibaba极简入门-分布式事务实战seata
在单体应用中通常情况下只有一个数据库(单数据源),集成事务是一个非常容易的工作。Spring对事务做了很好的管理,我们只需要通过简单的注解@Transactional就可以完成本地事务管理。 但是在微服务项目中事务的管理变得困难,因为微服务项目往往有很多的数据库组成,如果在一个业务中涉及到了对多个微服务以及多个数据库的写操作(跨多个数据源),那么要如何才能保证多个数据库组件的读写一致呢?即:同时操作两个数据库,数据库A写操作成功过,数据库B写操作失败要怎么样让数据库A的写操作回滚?很显然用本地事务管理是不能实现了。 我们知道,虽然Spring对事务做了很好的管理和封装,但是最终都是调用数据
|
SQL 存储 机器学习/深度学习
(二十)、SpringCloud Alibaba Seata处理分布式事务
(二十)、SpringCloud Alibaba Seata处理分布式事务
(二十)、SpringCloud Alibaba Seata处理分布式事务