SpringCloud+Nacos项目集成Seata分布式事务

上一篇: 《 Seata-分布式事务介绍 》: 简单介绍了分布式事务的实现方式,以及详细讲述了Seata-AT模式的两阶段提交步骤流程。

完整示例项目代码地址: https://gitee.com/cnyunze/yz-seata.git

Seata快速上手

  • 安装教程
    • Seata Server(TC端)简介
    • Seata部署
      • 1. 下载安装包
      • 2. 创建seata服务端数据库表
      • 3. 注册中心
      • 4. 配置中心
      • 5. 启动seata
    • 事务分组与高可用
  • 项目集成
    • 1. 环境准备
    • 2. 微服务均引入seata依赖
    • 3. AT模式--创建undo_log日志表
    • 4. 微服务配置application.yml添加seata相关配置信息
    • 5. 在代码里添加全局事务
    • 6. 测试验证分布式事务是否生效

安装教程

组件版本关系

组件版本
JDK1.8.0_333
Spring Boot2.6.13
Spring Cloud2021.0.5
Spring Cloud Alibaba2021.0.5.0
Nacos2.1.2
Seata1.6.1
MySQL8.0.33

其他版本依赖关系可以参考阿里的wiki文档:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

上文 《Seata-分布式事务介绍 》里有提到,Seata分 TC、TM 和 RM 三个角色,其中TC(Server端)为单独服务端部署,TM 和 RM(Client端)由业务系统集成。

Seata Server(TC端)简介

Seata的server端的数据存储模式现在支持三种:filedbredis

  • **file:**适用单机模式,不支持集群高可用(HA),全局事务会话信息在内存中读写并会持久化到本地文件,性能较高。
  • **db:**支持高可用集群模式(HA),全局事务会话信息通过数据库进行共享,但是相对性能会差一些。
  • **redis:**支持高可用集群模式(HA),但是由于redis的数据持久化机制,会存在事务信息丢失的风险。

本文使用db模式,相关脚本地址:https://github.com/seata/seata/tree/1.6.1/script

client目录里面放的是业务系统集成所需的脚本(例如AT模式所需要的 undo_log 日志表)。

config-center目录里面放的是各类配置中心所需要导入的配置参数信息,其中 config.txt 文件里包含了server端和client端的通用参数信息。

server目录里面为server端也就是 TC 所需的数据库建表脚本,及各个容器的配置。

image-20231203213436648

Seata部署

采用db存储模式 + Nacos(注册中心&配置中心)方式部署Seata服务端。

1. 下载安装包

下载地址:https://github.com/seata/seata/releases

windows系统下载zip的包,linux系统下载tar.gz的包。

image-20231203215255520

2. 创建seata服务端数据库表

创建seata服务端所需数据库,并执行脚本,sql脚本地址:https://github.com/seata/seata/blob/1.6.1/script/server/db/mysql.sql

image-20231203215651832

3. 注册中心

什么是注册中心?注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用.比如Seata Client端(TM,RM),发现Seata Server(TC)集群的地址,彼此通信。

nacos注册中心

​ 在配置Seata注册到nacos的注册中心之前,请先确保已经启动了Nacos服务。(Nacos的基本使用可参考Nacos 快速入门)

调整Seata Server的application.yml配置文件,使seata注册到指定的nacos(127.0.0.1:8848),指定的命名空间(namespace为空的时候,默认注册到public空间里),指定的分组(SEATA_GROUP),加入到指定的cluster集群(guangzhou)。

image-20231203220844190

seata:registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: ""cluster: guangzhouusername: nacospassword: nacos

Tips:请确保此处的server端服务与下文的client端服务是注册在同一个namespace和group,不然会找不到服务。

4. 配置中心

什么是配置中心?配置中心可以说是一个"大货仓",内部放置着各种配置文件,你可以通过自己所需进行获取配置加载到对应的客户端.比如Seata Client端(TM,RM),Seata Server(TC),会去读取全局事务开关,事务会话存储模式等信息。

nacos配置中心

​ 调整Seata Server的application.yml配置文件,使seata到指定的nacos(127.0.0.1:8848),指定的命名空间(f0357fda-3e2d-42ae-ac6f-3848aaecf0db),指定的分组(SEATA_GROUP),去读取指定的配置文件(seataServer.properties)。

seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: f0357fda-3e2d-42ae-ac6f-3848aaecf0dbdataId: seataServer.propertiesusername: nacospassword: nacos

image-20231203234129964

其中 seataServer.properties 的配置内容为\seata-server-1.6.1\script\config-center\config.txt文件的配置信息,全文复制然后修改几个关键配置即可。

nacos里调整 seataServer.properties 配置里的如下几个关键信息

#Transaction routing rules configuration, only for the client
#service.vgroupMapping.default_tx_group=default
service.vgroupMapping.t_mall_tx_group=guangzhou#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#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata1.6.1?useUnicode=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
store.db.user=seata
store.db.password=seata

Tips:(注意:store.db.driverClassName)

注意上述配置里的 store.db.driverClassName 如果是mysql8,则一定要改为 com.mysql.cj.jdbc.Driver,默认的 com.mysql.jdbc.Driver 会导致在启动seata server启动时提示数据库连接获取失败。mysql5没有进行测试,可以自行验证一下。

(数据库驱动放在目录:\seata-server-1.6.1\lib\jdbc)

Tips:(注意:store.db.url)

当seata使用db模式时,seata是通过jdbc的executeBatch来批量插入全局锁,所以连接参数store.db.url中的 rewriteBatchedStatements 为true时,可在批量插入使,性能提升10倍有余。(在执行executeBatch,并且操作类型 为insert时,jdbc驱动会把对应的SQL优化成insert into () values (),()的形式来提升批量插入的性能)

重点注意(这一块如果暂时不理解,可与先跟着文档配,等项目跑来之后,可以自己再一点点去调整、去验证、然后理解这个配置的用途)

Tips:(重点注意:service.vgroupMapping.t_mall_tx_group)

seata.service.vgroup-mapping.事务分组名=集群名称

其中"集群名称"需要和Seata Server注册到nacos的cluster配置 [seata.registry.nacos.cluster](#3. 注册中心) 以及下文中client端里配置seata.service.vgroup-mapping.t_mall_tx_group(事务分组名)保持一致。

事务分组名称需要和下文的应用程序里集成seata的client端里配置的 seata.tx-service-group([跳转查看](#4. 微服务配置application.yml添加seata相关配置信息)) 保持一致。

5. 启动seata

windows系统启动双击seata-server.bat脚本即可;

linux系统启动使用seata-server.sh脚本,启动命令:

./seata-server.sh

image-20231204231318048

启动之后可以到 nacos 上看到注册的seata服务

image-20231204231612562

image-20231204231642593

其中分组 SEATA_GROUP 对应seata服务的application.yml配置文件里 seata.registry.nacos.group 配置;

集群 guangzhou 对应seata服务的application.yml配置文件里 seata.registry.nacos.cluster 配置;

事务分组与高可用

官方文档:http://seata.io/zh-cn/docs/v1.6/user/txgroup/transaction-group-and-ha

项目集成

完整代码示例地址:https://gitee.com/cnyunze/yz-seata.git

1. 环境准备

现有一个项目yz-seata,项目下有3个微服务:

yz-seata-mall-account:用户账号管理服务,负责记录账户余额;

yz-seata-mall-order:订单管理服务,负责记录用户购买商品记录信息;

yz-seata-mall-storage:库存管理服务,负责记录各商品的剩余库存量;

2. 微服务均引入seata依赖

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

3. AT模式–创建undo_log日志表

各微服务所对应的数据库里都需要添加一个undo_log日志表,该表用于事务数据回滚;

脚本地址:https://github.com/seata/seata/blob/1.6.1/script/client/at/db/mysql.sql

```sql
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(`branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',`xid`           VARCHAR(128) 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 = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
```

image-20231205000028280

4. 微服务配置application.yml添加seata相关配置信息

seata:application-id: ${spring.application.name}# seata 服务分组,要与服务端配置service.vgroup_mapping的后缀对应tx-service-group: t_mall_tx_groupservice:vgroup-mapping:t_mall_tx_group: guangzhouregistry:type: nacosnacos:application: seata-servergroup: SEATA_GROUPconfig:type: nacosnacos:server-addr: 127.0.0.1:8848namespace: f0357fda-3e2d-42ae-ac6f-3848aaecf0dbgroup: SEATA_GROUPdata-id: seataServer.properties

注意:

seata.tx-service-group 要与上文的服务端配置 service.vgroup_mapping (跳转查看 )的后缀对应。

seata.service.vgroup-mapping.事务分组名=集群名称 也要与上文 seataServer.properties 配置文件里的 service.vgroupMapping.t_mall_tx_group=guangzhou 保持一致。

5. 在代码里添加全局事务

在全局事务发起者方法上面添加@GlobalTransactional全局事务注解。

全局事务发起者:判断方法为,是谁最先去调用其他微服务接口的方法,就是全局事务的发起者;

例1:用户下了个订单,先请求订单服务,新增订单方法,然后新增订单方法里又去调用库存服务的扣减库存方法、用户账号服务的扣减余额方法,则新增订单方法就是全局事务的发起者;

例2:用户下了个订单,先扣减用户账号的余额,扣减余额方法又去调库存服务的扣减库存方法、订单服务的新增订单方法,则用户账号服务的扣减余额方法就是全局事务的发起者;

例:

	/*** 单纯使用@Transactional注解存在如下问题:* 如果订单新增成功,库存扣减成功,但扣减余额的时候失败了,则扣减的余额会回滚,新增的订单信息会回滚,但是已经扣减的库存却不会再回滚*/@GlobalTransactional(name = "addOrder", rollbackFor = Exception.class)@Overridepublic TOrder saveOrder(TOrder tOrder) {tOrder.setId(IdUtil.getSnowflakeNextId());// 新增订单信息baseMapper.insert(tOrder);// 扣减库存stockFeignService.deduct(tOrder.getProductId(), tOrder.getNum());// 扣减余额accountFeignService.deduct(tOrder.getAccountId(), tOrder.getAmount());return tOrder;}

6. 测试验证分布式事务是否生效

场景1:正常下单–>扣减库存–>扣减余额–>事务成功提交

场景2:正常下单–>扣减库存–>扣减余额(失败)–>验证事务是否回滚(扣减的库存是否有还原)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/198809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手学深度学习笔记

1. 深度学习基础与MLP 1.1 框架&#xff1a; 线性回归&#xff1b; Softmax回归&#xff08;实际上用于分类问题&#xff09;&#xff1b; 感知机与多层感知机&#xff1b; 模型选择&#xff1b; 权重衰退&#xff08;weight decay&#xff09;&#xff1b; 丢弃法&…

sql面试题之累计消耗问题

sql中累计求和是我们比较经常遇到的问题&#xff0c;那么与之相反的累计消耗的问题不知你是否挑战过 –问题&#xff1a;在活动大促中&#xff0c;有玩游戏瓜分奖金环节。现有奖金池为3000元&#xff0c;代表奖金池中的初始额度 表中的数据代表每一个用户和其对应的得分&#…

Java 并发编程面试题——Java 线程间通信方式

目录 1.✨Java 线程间有哪些通信方式&#xff1f;1.1.volatile 和 synchronized 关键字1.2.等待/通知机制1.2.1.概述1.2.2.经典范式 1.3.管道输入/输出流1.4.信号量 2.Thread.join() 有什么作用&#xff1f;它的使用场景是什么&#xff1f;3.Java 中需要主线程等待子线程执行完…

java:封装统一的响应体code、data、msg、paging

背景 我们在写接口的时候一般不会直接返回给前端数据&#xff0c;而是会有响应体&#xff0c;比如 code、data、msg&#xff0c;这样就有一个统一的结构方便前端处理&#xff0c;那么今天就来封装一个统一的响应体 封装基本响应体 1、在 config 包里新建 ApiResponse.java …

5+铜死亡+预后模型+分型生信思路,热点搭配免疫相关思路

今天给同学们分享一篇生信文章“The pathogenesis of DLD-mediated cuproptosis induced spinal cord injury and its regulation on immune microenvironment”&#xff0c;这篇文章发表在Front Cell Neurosci期刊上&#xff0c;影响因子为5.3。 结果解读&#xff1a; 基因芯…

LeetCode - 110. 平衡二叉树(C语言,二叉树,配图,简单)

根据题意&#xff0c;我们只需要比较当前节点的左右子树高度差是否小于1&#xff0c;利用分治法&#xff0c;只需要满足&#xff1a; 1. 根节点的左右子树的高度差小于1。 2. 根节点左右子树的满足高度差小于1&#xff0c;在往下走&#xff0c;判断左子树根节点的左右子树是否满…

质量检查管理制度

质量检查管理制度 建立健全质量检查管理制度&#xff0c;明确过程检查、最终检查、质量评定、检查记录和检查报告等要求

40.坑王驾到第六期:这是什么奇葩错误?

一、问题再现 在HbuilderX中引用了一个checkALL模块&#xff0c;正常编译然后启动到微信开发者工具&#xff0c;工具报错&#xff0c;找不到XXXXXX/index2.js。为什么编译后在微信工具中会自动加一个2呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; 二、解决问题 经过清…

【Node.js】基础梳理 6 - MongoDB

写在最前&#xff1a;跟着视频学习只是为了在新手期快速入门。想要学习全面、进阶的知识&#xff0c;需要格外注重实战和官方技术文档&#xff0c;文档建议作为手册使用 系列文章 【Node.js】笔记整理 1 - 基础知识【Node.js】笔记整理 2 - 常用模块【Node.js】笔记整理 3 - n…

【LeetCode】每日一题 2023_12_5 到达首都的最少油耗(树,搜索)

文章目录 刷题前唠嗑题目&#xff1a;到达首都的最少油耗题目描述代码与解题思路 刷题前唠嗑 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;到达首都的最少油耗 题目链接&#xff1a;2477. 到达首都的最少油耗 题目描述 代码与解题思路 …

Python代码编译并生成Docker镜像

Python代码编译并生成Docker镜像 前言 实际python项目交付时往往有针对关键代码进行保护的需求&#xff0c;本文介绍了一种简单可行的方案&#xff1a;1. 在Linux系统上先将 .py 文件编译为 .so 文件&#xff0c;2. 将整个项目打包成Docker镜像&#xff08;解决 .so 文件的环…

【性能测试】业务/吞吐量与存量数据设计关系+压测常见解决方案

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、性能测试中业务…

C语言错误处理之 “信号处理方式<signal.h>及signal函数等内置函数”

目录 前言 signal.h头文件 信号宏 signal函数 实例&#xff1a;在Linux环境下验证signal函数 实例&#xff1a;在Linux中演示保存signal函数的返回值 预定义的信号处理函数&#xff08;简单了解&#xff09; SIG_DFL函数 SIG_IGN函数 raise函数 实例&#xff1a;测试…

leetcode 255.用队列实现栈

255.用队列实现栈 不出意外大概率这几天都会更新 leetcode&#xff0c;如果没有做新的题&#xff0c;大概就会把 leetcode 之前写过的题整理&#xff08;单链表的题目居多一点&#xff09;出来写成博客 今天讲的题蛮容易出错的&#xff08;注意传参啊&#xff0c;最好把队列的…

渗透测试——五、网站漏洞——SQL注入

一、走进DVWA测试网站 1、网站渗透测试步骤 (1)收集信息 1、获取域名的 Whois 信息&#xff0c;获取注册者邮箱、姓名、电话等。2、查询服务器旁站及子域名站点&#xff0c;因为主站一般比较难&#xff0c;所以先看看旁站有没有通用性的CMS或者其他漏洞。3、查看服务器操作系…

ROS话题通信基本操作(C++)

目录 一、发布 1、实现步骤 2、代码实例 二、接收 1、实现步骤 2、代码实例 三、配置运行 1、修改CMakeLists.txt 2、运行结果 一、发布 1、实现步骤 1.包含头文件 2.初始化 ROS 节点:命名(唯一) 3.实例化 ROS 句柄 4.实例化 发布者 对象 5.组织被发布的数据&#…

Pytest做性能测试?

Pytest其实也是可以做性能测试或者基准测试的。是非常方便的。 可以考虑使用Pytest-benchmark类库进行。 安装pytest-benchmark 首先&#xff0c;确保已经安装了pytest和pytest-benchmark插件。可以使用以下命令安装插件&#xff1a; pip install pytest pytest-benchmark …

JSP控制项目启动后默认去访问指定的WebServlet 而不是index.jsp

我的 index.jsp 代码是这样 现在每次启动 访问的都是index.jsp 这也是它的默认配置 我这里写了一个 WebServlet 代码是这样 简单可以理解为 我们定义了WebServlet 访问路径为1cginServlet 其中在request作用域中 定义了一个userName值为 欢迎来到jsp世界 然后 跳转向 page.j…

Android : AndroidStudio开发工具优化

1.开启 gradle 单独的守护进程 Windows: 进入目录 C:\Users\Administrator\.gradle 创建文件&#xff1a; gradle.properties # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Settings specified in this file will override any Gradle s…

前端时间的失败总结复盘

分享失败经验&#xff0c;前段时间的总结复盘&#xff1a; 与伙伴合作面对异常决策要及时提出质疑&#xff0c;怼&#xff0c;别太客气&#xff0c;客气起来&#xff0c;小心翼翼在意他人情绪那么这个项目就会让人难受&#xff0c;不要因为因为伙伴身上有标签/光环/权威就觉得…