记 Nacos 分布式事务Seata1.3的集成

本文档记录了Seata集成到SpringCloudAlibaba项目中的详细步骤,包括Seata的版本选择、依赖配置、数据库表创建、Nacos配置以及客户端配置。遇到的问题包括Seata与MySQL8的时区问题,以及Nacos配置的注意事项。通过这篇博客,读者可以了解到Seata的初步使用和配置要点。
摘要由CSDN通过智能技术生成

最近在做一个新项目需要用到seata 因为之前没用过所以去网上找资料的时候就很茫然 这里粘一点 那里扣一点 然后感觉各种问题都遇到了 陆陆续续的做了有两三天 终于现在能用了 这里记录一下踩过得坑和一些注意点 同时感谢各路大佬的帮助
这里先暂时将用法记录一下 等后面有时间了就从头开始学习一下Spring Cloud Alibaba 后续再进行补充 如果有推荐的课程大家可以评论一下 感谢~

查看springcloud 对应版本 :https://start.spring.io/actuator/info
官网里也能看到:https://spring.io/projects/spring-cloud#overview

seata下载地址:https://github.com/seata/seata/releases(这里选用的1.3版本的)
seata文档:https://seata.io/zh-cn/docs/overview/what-is-seata.html
seata源码及一些配置:https://github.com/seata/seata/tree/1.3.0

  • Spring Cloud Alibaba 版本 2.2.6.RELEASE
  • boot版本 2.3.12.RELEASE
  • Nacos版本1.4.2
  • Mysql版本 8.0.26

依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

数据库

数据库的文件在下载的源码里面
在这里插入图片描述
导入后就会有这三个表
在这里插入图片描述
还要在每个业务库里面建一个undo_log 用来回滚的表 后面再去了解他的用法

CREATE TABLE `undo_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `branch_id` bigint NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int 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;

server端

1. seata下载 解压

2. 修改配置文件

  1. file.conf
    先将store里面mode改成db,然后将数据库的连接信息改成自己的 注意如果是mysql8版本以上的要将驱动改成com.mysql.cj.jdbc.Driver
    在这里插入图片描述
  2. registry.conf
    把registry 里面的type改成nacos
    namespace改成nacos中的. 注意区分大小写
    用户名密码填上
    下面config也是一样 其他的不要可以删掉
    在这里插入图片描述
    在这里插入图片描述

3. 上传配置

之前我看一些文章中就是直接把配置复制到项目中的资源文件夹下面 后面看到其实也可以上传到nacos中去 效果都是一样的
在刚刚下载的seata源码中找到
在这里插入图片描述
配置

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=file
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

然后将数据库的连接信息修改成自己的
在这里插入图片描述
这里需要注意一个点就是 可能因为我是mysql8版本的 所以后面启动后要报一个乱码的错 后面说是什么时区问题 在url后面加上
?rewriteBatchedStatements=true&useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
这些就好啦

找到同目录下的nacos文件夹将这两个文件复制出来就行 放到seata目录下 可以直接双击运行上传
在这里插入图片描述
sh nacos-config.sh
可选参数

  • -h localhost //指定地址
  • -p 8848 //端口
  • -g SEATA_GROUP //组名
  • -t test //命名空间
  • -u nacos //用户名
  • -w nacos //密码

然后就能在配置中心中对应的命令空间里面看到配置信息 这里项目没启动 就不贴图了 配置也很多 有八页多 你也可以单独新开一个组存放

server端就配置好啦。


client端

client端配置

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

seata:
  tx-service-group: my_test_tx_group
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      username: "nacos"
      password: "nacos"
      group: SEATA_GROUP
      namespace: 
      cluster: default
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      username: "nacos"
      password: "nacos"
      namespace:

然后将@GlobalTransactional加在需要使用的方法上

后话 之前还加过DataSource的代理配置啥的 这个可能是之前的一些东西了 现在就不需要了 后面学习的还是再去理解理解


问题&报错

[ main] i.s.c.r.netty.NettyClientChannelManager : no available service ‘null’ found, please make sure registry config correct

no available service ‘null’ found, please make sure registry config correct

这个问题从我集成以来就时不时出现一下 意思就是说未找到服务 这里就是注意一下

在这里插入图片描述
这两个地方一定要和Nacos中的配置对应上 我当时就是因为命名空间忘了区分大小写所以一直出问题 😭

Seata的高可用模式是通过TC使用db模式共享全局事务会话信息,使用非file的seata支持的第三方注册中心和配置中心来共享全局配置的方式来实现的。 Seata支持的第三方注册中心有nacos 、eureka、redis、zk、consul、etcd3、sofa、custom,支持的第三方配置中心有nacos 、apollo、zk、consul、etcd3、custom。seata官方主推的应该是nacos(毕竟是一家的),但是由于本人平常使用的注册中心一直是zk,因此首先考虑通过zk作为注册中心来实现高可用模式。 环境准备 zk环境准备 本地已安装zk的可以忽略,如果本地未安装,先在本地安装zk,具体安装自行百度。 PS: 此处如果使用的是远程zk服务器,则本地可以只下载,不安装。 数据库环境准备 1、创建数据库seata 2、执行源码(version1.2.0)script -> server -> db 下面的mysql.sql文件,建立global_table,branch_table,lock_table表。 配置信息导入zk 1、打开本地seata源码(版本1.2.0) 2、编辑script -> config-center -> config.txt文件,修改store.mode=db,修改store.db相关的数据库连接信息,其它默认即可 3、进入script -> config-center ->zk,执行 sh zk-config.sh -h 127.0.0.1 -p 2181 -z /usr/local/zookeeper-3.4.14(-z 后面的参数为你本地zk目录) 上面命令会将config.txt中的配置信息写入zk的/seata节点下。 启动tc-server 1、编辑conf下面的registry.conf文件,修改registry.type=zk,修改config.type=zk,修改registry.zk及config.zk信息,如下: 注意:config的zk配置没有cluster属性。 2、启动server,在本地seata安装目录bin目录下执行./seata-server.sh -m db (此处也可以直接编译本地源码然后启动Server模块下的Server类)。 不出意外的话,启动会报错,错误信息是从zk读取配置的时候反序列化出问题。 错误原因:序列化问题,由于使用seata自带的zk-config.sh脚本向zk写入配置信息的时候,采用的序列化方式相当于String.getBytes(),而框架读取配置的时候使用的是org.101tec包中的Zkclient客户端,反序列化使用的是该包下面的SerializableSerializer序列化类,使用的ObjectOutputStream进行反序列化,和序列化方式不一致。 该问题在1.3.0版本中解决,解决方式是seata支持序列化方式配置,支持自定义序列化方式,同时提供默认序列化实现类DefaultZkSerializer,反序列化实现为new String()。 到此处,1.2.0版本无法进行下去,由于目前1.3.0正式版本还未出,只能拉取最新的开发分支源码,本地编译打包1.3.0-SNAPSHOT版本。 后续版本切为1.3.0-SNAPSHOT(20200701),删除原zk配置信息重新导入1.3版本的config.txt文件信息。 本地源码编译后直接Idea启动Server类。启动成功。 PS:启动日志里面会有一些getConfig失败的报错,这些不用管,这些新的配置参数是1.3版本新增的,由于当前是SNAPSHOT版本,还不完善。 PS: 如果遇到getServerCharset 空指针异常,这个主要是MySQL和MySQL驱动版本不一致引起的,看https://blog.csdn.net/zcs20082015/article/details/107087589 服务启动 配置修改 简单处理,这里不再建新的模块,直接使用zhengcs-seata-storage模块作为演示。 1、修改POM,引入zkclient,修改seata版本 2、修改application.yml,将注册和配置类型改为zk 另外需要注意的是seata.tx-service-group配置参数要和zk导入的配置信息相关参数保持一致,否则会找不到server集群 启动服务 1、引入全局事务 2、启动 测试 基本功能测试 单元测试用例: 手动插入异常 执行用例: 基本功能是没问题的,更详细全面的测试这里就不介绍了,大家自行尝试。 高可用测试 上面的单机版肯定无法满足高可用,tc-server一旦宕掉,整个全局事务会无法进行回滚,同时会在seata库下面的事务表里面留下事务录(正常处理成功后会被删除)。 seata的高可用是通过多个tc-server实例组成的集群来实现的。 启动多个tc-server实例: 通过-p参数修改启动接口,同时勾选Allow parallel run,开启多个实例。 然后启动客服端服务: 从启动日志可以看出,客户端会同时向所有几点注册TM和RM。 执行测试用例: 那,如果在数据已提交,异常退出之前把对应的tc-server节点停掉,会怎么样呢?答案是:全局事务回滚。大家自行尝试一下。 还有一种情况,如果客户端在执行过程中中断了,会怎么样? 如果客户端是单节点部署,那么: 首先,seata库下面的事务处理表里面有遗留事务处理录,然后你会发现tc-server端日志里面会持续刷上述日志,tc-server会持续的尝试回滚该事务。最遗憾的是:哪怕客户端服务重启,也不会回滚该事务!!! 不过还好的是,这种情况毕竟是特例,如果客户端服务是集群部署,那么seata是可以正常完成事务回滚的。 结语 从上面的情况来看,起码seata对于简单的分布式事务场景的高可用支撑是没问题的,但是seata毕竟还是一个新框架,在实际的复杂的业务场景下会否出现什么问题,其实应该说出现什么问题都是可能的,这个需要实践和时间才能出真知了。 另外,seata目前没有提供控制台,没有服务集群配套的HA机制,这个不知道什么时候会出,拭目以待,seata应该会是一个很不错的分布式事务解决方案。   参考资料 https://seata.io/zh-cn/docs/ https://github.com/seata/seata ———————————————— 版权声明:本文为CSDN博主「zhengcs已被占用」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zcs20082015/article/details/107092936
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值