Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心

Posted 程序员陆通

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心相关的知识,希望对你有一定的参考价值。

Spring Cloud Seata 分布式事务使用快速入门

特点

1、文档教程详细且提供完整源码及数据库脚本
2、有配套全手敲代码的视频演示教程

使用版本

Spring Cloud Alibaba 2021.1
Nacos 1.4.1
Seata 1.3.0

概念说明:本地事务及分布式事务

本地事务

1、在一个进程中
2、在同一个数据库中

分布式事务及产生

1、多个进程:每个微服务一个进程。

2、每个微服务对应一个数据库或多个微服务对应一个数据库。

3、一个事务需要订单、商品、用户三个微服务上面同时操作成功才算事务全部完成,否则就要回滚。就是说
​ 三个本地事务组成了一个分布式事务。
总结:分布式事务=本地事务1+本地事务2+本地事务N

分布式事务怎么解决

思路:需要有个局外人(事务协调者),统计记录多个本地事务执行情况,所有本地事务全部执行成功,他说成功才算成功。同时如果多个本地事务分别执行过程中,如果哪个出错了,事务协调者要对之前已经执行的操作进行回滚。
举例:

三个人的接力赛,比赛三人配合,某个人只跑完自己的那段不算赢。裁判是根据最终三个人都完成请速度最快来决定胜负。

演示本地事务异常回滚代码

Seata是什么

1、开源的分布式事务解决方案框架

2、提供AT、TCC、SAGA及XA模式

3、目标:对业务无侵入,高性能

4、是裁判记录员(类比)

Seata的AT模式

简化模型:


两阶段提交协议的演变:

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。

二阶段:所有本地事务都正常执行就算成功,某个异常时,通过一阶段的回滚日志进行反向补偿。

二阶段提交的详细实现:

第一阶段:

1、不同微服务(相当于一个分支)做了一新增、修改(Update)或删除(Delete)操作,Seata把新增、修改或删除前后的数据记录下来,即原始数据及操作后的数据,分别为前镜像数据和后镜像数据。

2、把这2个数据插入undo_log日志表

3、拿到更新(修改或删除)数据对应id的全局锁

4、将业务更新数据及undo log日志数据同时本地事务提交

5、把提交结果告知给事务协调者(分支提交结果给协调者)

第二阶段:

提交(正常情况):

事务协调者提交事务并且把undo log日志中的数据删除。

回滚(异常情况):

分支回滚请求后,找到对应的undo log日志进行回滚操作

安装使用

版本对应说明

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

Spring Cloud Alibaba 是2021.1,所以Seata使用1.3.0

Seata相关组件下载及配置

下载:

seata-server-1.3.0.zip : 事务协调者服务端 https://github.com/seata/seata/releases/tag/v1.3.0

seata-1.3.0.zip : Seata 1.3配置及脚本 https://github.com/seata/seata/tree/v1.3.0

配置及启动seata-server(事务协助者服务):

1、修改Seata事务协调者数据存储方式

1.1、修改Seata事务协调者服务端的数据存储方式为数据库(默认是file文件)

文件在seata-server\\conf\\file.conf中

store 
  mode = "db"
  db 
    datasource = "druid"
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "123456"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  

1.2、在MySQL中创建seata数据库,然后执行建表语句

seata-1.3.0\\script\\server\\db\\mysql.sql

2、修改Seata事务协调者的注册中心配置

seata-server\\conf\\registry.conf

设置Seata事务协调者服务注册到Nacos上

registry 
  type = "nacos"
  nacos 
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP" 
    namespace = "e98fe52a-5a5d-4c55-98b8-cb867e045e18"  //在Nacos中新建的seata命名空间的ID
    cluster = "default"
    username = "nacos"
    password = "nacos"
  

设置Seata事务协调者的配置信息由Nacos的配置中心进行管理

config 
  type = "nacos"
  nacos 
    serverAddr = "127.0.0.1:8848"
    namespace = "e98fe52a-5a5d-4c55-98b8-cb867e045e18"
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos"
  

3、添加Seata的配置信息到Nacos配置中心上

3.1、把seata-1.3.0\\script\\config-center\\config.txt中所有配置信息添加到Nacos配置中心上

修改33行及40到45行

transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
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
service.vgroupMapping.my_test_tx_group=default
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
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=false
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
store.mode=db
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=username
store.db.password=password
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
store.redis.host=127.0.0.1
store.redis.port=6379
store.redis.maxConn=10
store.redis.minConn=1
store.redis.database=0
store.redis.password=null
store.redis.queryLimit=100
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

操作:

进入seata-1.3.0\\script\\config-center\\nacos目录,会看到nacos-config.py和nacos-config.sh两个文件,其中nacos-config.sh即为把seata-1.3.0\\script\\config-center\\config.txt文件中的所有配置信息推送到Nacos配置中心的脚本工具。

其原来为执行Nacos的发布配置接口。https://nacos.io/zh-cn/docs/open-api.html

在此目录下开启Git base窗口,执行如下命令

$ sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 命名空间ID -u 用户名称 -w 密码

说明:Git base创建打开需要安装Git客户端 ,下载地址:https://git-scm.com/downloads

4、启动事务协调者

执行seata-server\\bin\\seata-server.bat

分布式事务代码案例演示:

微服务调用链路图:

1、建库建表

创建3个数据库及对应的表(其中业务微服务不需要创建数据库)

数据库:

stock_tbl表、undo_log表

CREATE TABLE `stock_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

seata-1.3.0\\script\\client\\at\\db\\mysql.sql

CREATE TABLE IF NOT EXISTS `undo_log`
(
    `branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',
    `xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',
    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',
    `log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';

seata_lutong_account数据库

account_tbl表、undo_log表

CREATE TABLE `account_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

seata_lutong_order数据库

order_tbl表、undo_log表

CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT '0',
  `money` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

2、创建微服务代码

新建stock-service微服务

添加配置:

server:
  port: 8024
spring:
  application:
    name: stock-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: e98fe52a-5a5d-4c55-98b8-cb867e045e18
        group: SEATA_GROUP
  datasource:
      url: jdbc:mysql://localhost:3306/seata_lutong_stock
      driverClassName: com.mysql.jdbc.Driver
      username: root
      password: 123456
seata:
  application-id: stock-service
  tx-service-group: seata-storage-tx-group #事务分组
  config:
    type: nacos
    nacos:
      namespace: e98fe52a-5a5d-4c55-98b8-cb867e045e18
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      username: nacos
      password: nacos
  registry:
    nacos:
      application: seata-server
      group: SEATA_GROUP
      namespace: e98fe52a-5a5d-4c55-98b8-cb867e045e18
      username: nacos
      password: nacos
      server-addr: 127.0.0.1:8848

3、在Nacos中添加配置项目:

同样的方法编写account-service、order-service、business-service

编写代码较多,可以观看视频来学习操作(这节视频设置免费的,如下链接)

https://download.csdn.net/course/detail/36097

4、Seata使用避坑

1、endpoint format should like ip:port异常

service.vgroupMapping.事务分组名称=default或者在application.yml中添加也可以。

如果不添加会出现如下错误:

Failed to get available servers: endpoint format should like ip:port
java.lang.IllegalArgumentException: endpoint format should like ip:port
2、undo_log插入异常

要设置undo_log日志表的branch_id字段为主键(原来的脚本是没有设置的)

io.seata.common.exception.NotSupportYetException: undo_log needs to contain the primary key.

视频和示例代码获取

视频教程地址:
https://download.csdn.net/course/detail/36097
源码下载地址:
https://github.com/laolujava/spring-cloud-alibaba-tutorial

以上是关于Spring Cloud Alibaba Seata 分布式事务使用快速入门,Nacos做Seata的注册中心和配置中心的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Alibaba系列教程——Spring Cloud Alibaba开篇

spring boot 整合spring cloud alibaba

spring boot 整合spring cloud alibaba

深度剖析Spring Cloud Alibaba系列——如何兼容Spring Cloud

Spring Cloud Alibaba Sentinel集成

五分钟带你玩转spring cloud alibaba越玩越溜!实战Spring Cloud Alibaba Sentinel