Seata 2.x 系列【8】Spring Cloud 集成客户端

有道无术,术尚可求,有术无道,止于术。

本系列Seata 版本 2.0.0

本系列Spring Boot 版本 3.2.0

本系列Spring Cloud 版本 2023.0.0

源码地址:https://gitee.com/pearl-organization/study-seata-demo

文章目录

    • 1. 前言
    • 2. 问题演示
    • 3. 客户端集成
      • 3.1 引入依赖
      • 3.2 配置
      • 3.3 undo_log 表
      • 3.4 开启全局事务
      • 3.5 启动
    • 4. 测试

1. 前言

在前几篇文档中,我们部署好了Seata服务端并集成了Nacos,也搭建了一个微服务项目并实现了电商下单功能,接下来,我们学习如何Spring Cloud集成Seata客户端,并解决分布式事务问题(默认使用的是AT模式)。

2. 问题演示

假如在整个电商下单的流程中,扣除账户余额时,发生了异常:
在这里插入图片描述

    @Override@Transactionalpublic ObjectResponse decreaseAccount(AccountDTO accountDTO) {// 扣减余额int account = baseMapper.decreaseAccount(accountDTO.getUserId(), accountDTO.getAmount().doubleValue());// 模拟异常if (1==1){throw new RuntimeException("扣除失败~~");}ObjectResponse<Object> response = new ObjectResponse<>();if (account > 0) {response.setStatus(RspStatusEnum.SUCCESS.getCode());response.setMessage(RspStatusEnum.SUCCESS.getMessage());return response;}response.setStatus(RspStatusEnum.FAIL.getCode());response.setMessage(RspStatusEnum.FAIL.getMessage());return response;}

操作前,数据库中账户余额为10000,库存为10000,订单数为0,访问http://localhost:8080/business/buy下单接口,账户服务发生异常,由于开启了本地事务,账户回滚 ,订单服务调用账户服务返回异常,也因为开启了本地事务,插入的订单进行了回滚。

但是用于的库存服务本身并没有抛出任何异常,本地事务进行了提交,导致扣减了库存,发生数据不一致问题:
在这里插入图片描述

3. 客户端集成

3.1 引入依赖

在当前案例项目中,以下几个服务都是分布式事务的参与者,所以都需要集成Seata客户端:
在这里插入图片描述
Spring Cloud Alibaba已经提供了Spring Cloud环境下Seata的集成包,只需要引入以下依赖即可:

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

Seata客户端依赖为最新的2.0.0版本:
在这里插入图片描述

3.2 配置

在所有服务后台application.yml文件中,添加注册、配置中心:

seata:# 配置中心config:type: nacosnacos:# 通过 Nacos 获取 Seata 配置(以下配置需要和服务端保持一致)namespace: 7032916a-19f1-482e-a3eb-8a62226c2e4dserver-addr: 127.0.0.1:8848group: SEATA_GROUPdata-id: seata.properties# 注册中心registry:type: nacosnacos:# 通过 Nacos 服务发现 Seata 服务端(以下配置需要和服务端保持一致)# Seata 服务端在Nacos中注册的服务名application: seata-serverserver-addr: 127.0.0.1:8848group: DEFAULT_GROUPnamespace: 7032916a-19f1-482e-a3eb-8a62226c2e4d

3.3 undo_log 表

AT模式中,需要在参与全局事务的数据库中添加undo_log表:

-- seata_account.undo_log definitionCREATE TABLE `undo_log` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',`branch_id` bigint NOT NULL COMMENT '分支事务ID',`xid` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务唯一标识',`context` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8_general_ci NOT NULL COMMENT '上下文',`rollback_info` longblob NOT NULL COMMENT '回滚信息',`log_status` int NOT NULL COMMENT '状态,0正常,1全局已完成(防悬挂)',`log_created` datetime NOT NULL COMMENT '创建时间',`log_modified` datetime NOT NULL COMMENT '修改时间',PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='AT模式回滚日志表';

seata_accountseata_orderseata_stock库中,都新建undo_log表。

3.4 开启全局事务

下单流程由business服务发起,所以该服务即事务的发起方TM,我们在事务发起方法上添加@GlobalTransactional注解开启全局事务:

    @GlobalTransactionalpublic Object handleBusiness() {ObjectResponse<Object> objectResponse = new ObjectResponse<>();// 1. 业务请求数据BusinessDTO businessDTO =new BusinessDTO();// 省略..........
}

3.5 启动

启动所有业务服务,查看控制台,我们看下Seata相关的一些关键日志。

使用Nacos注册中心:

main] i.s.discovery.registry.RegistryFactory   : use registry center type: nacos

获取到Seata服务端地址并订阅:

main] com.alibaba.nacos.client.naming          : init new ips(1) service: DEFAULT_GROUP@@seata-server@@default -> [{"instanceId":"192.168.142.1#8091#default#DEFAULT_GROUP@@seata-server","ip":"192.168.142.1","port":8091,"weight":1.0,"healthy":true,"enabled":true,"ephemeral":true,"clusterName":"default","serviceName":"DEFAULT_GROUP@@seata-server","metadata":{},"ipDeleteTimeout":30000,"instanceHeartBeatInterval":5000,"instanceHeartBeatTimeOut":15000,"instanceIdGenerator":"simple"}]
main] com.alibaba.nacos.client.naming          : current ips:(1) service: DEFAULT_GROUP@@seata-server@@default -> [{"instanceId":"192.168.142.1#8091#default#DEFAULT_GROUP@@seata-server","ip":"192.168.142.1","port":8091,"weight":1.0,"healthy":true,"enabled":true,"ephemeral":true,"clusterName":"default","serviceName":"DEFAULT_GROUP@@seata-server","metadata":{},"ipDeleteTimeout":30000,"instanceHeartBeatInterval":5000,"instanceHeartBeatTimeOut":15000,"instanceIdGenerator":"simple"}]
main] com.alibaba.nacos.client.naming          : [SUBSCRIBE-SERVICE] service:seata-server, group:DEFAULT_GROUP, clusters:default 

使用Netty端口连接到Seata服务端,并发送TM注册请求:

main] i.s.c.r.netty.NettyClientChannelManager  : will connect to 192.168.142.1:8091
main] i.s.core.rpc.netty.NettyPoolableFactory  : NettyPool create channel to transactionRole:TMROLE,address:192.168.142.1:8091,msg:< RegisterTMRequest{version='2.0.0', applicationId='stock', transactionServiceGroup='default_tx_group', extraData='ak=null
digest=default_tx_group,192.168.142.1,1710149283844
timestamp=1710149283844
authVersion=V4
vgroup=default_tx_group
ip=192.168.142.1
'} >

TM注册成功,应用IDaccount(后台服务名),事务分组为default_tx_group(默认的,后续讲解):

main] i.s.c.rpc.netty.TmNettyRemotingClient    : register TM success. client version:2.0.0, server version:2.0.0,channel:[id: 0x9902a1f6, L:/192.168.142.1:53418 - R:/192.168.142.1:8091]
main] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 40 ms, version:2.0.0,role:TMROLE,channel:[id: 0x9902a1f6, L:/192.168.142.1:53418 - R:/192.168.142.1:8091]
main] i.s.s.a.GlobalTransactionScanner         : Transaction Manager Client is initialized. applicationId[stock] txServiceGroup[default_tx_group]

数据源初始化完成后,注册RM

main] i.s.s.a.GlobalTransactionScanner         : Resource Manager is initialized. applicationId[stock] txServiceGroup[default_tx_group]
main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@15a0f9
main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
main] i.s.c.r.netty.NettyClientChannelManager  : will connect to 192.168.142.1:8091
main] i.s.c.rpc.netty.RmNettyRemotingClient    : RM will register :jdbc:mysql://127.0.0.1:3306/seata_stock
main] i.s.c.rpc.netty.RmNettyRemotingClient    : register RM success. client version:2.0.0, server version:2.0.0,channel:[id: 0xd20fcff4, L:/192.168.142.1:53423 - R:/192.168.142.1:8091]
main] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 8 ms, version:2.0.0,role:RMROLE,channel:[id: 0xd20fcff4, L:/192.168.142.1:53423 - R:/192.168.142.1:8091]

最后可以看到默认开启了AT模式的数据源代理,说明AT是默认开启的事务模型:

main] .s.s.a.d.SeataAutoDataSourceProxyCreator : Auto proxy data source 'dataSource' by 'AT' mode.

4. 测试

重启所有服务后台,访问下单接口,可以看到在库存服务中,虽然没有抛出异常,但是全局事务失败了,进行了回滚操作:
在这里插入图片描述
查看数据库,所有数据一致,集成成功:
在这里插入图片描述

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

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

相关文章

裸辞18K外包,面试阿里、字节全都一面挂,哭死.....

测试员可以先在外包积累经验&#xff0c;以后去大厂就很容易&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓今年今天履历只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大…

iptables详细介绍

在 CentOS 中,iptables 是一种用于配置和管理网络防火墙的工具,它提供了一种灵活和强大的方式来控制进出服务器的网络流量。以下是 CentOS 中 iptables 的主要内容: 规则链(Chains): iptables 使用规则链来组织规则,常见的链包括: INPUT:处理进入服务器的数据包。OUTP…

固定资产管理系统:井然有序,提升利用率,降损增值的解决之道。

固定资产管理系统是一种用于管理和跟踪组织内固定资产的软件系统。固定资产是指组织长期持有并用于生产、运营或提供服务的资产&#xff0c;例如土地、建筑物、机器设备、车辆等。 固定资产管理系统提供了一种集中管理和监控固定资产的方式&#xff0c;帮助组织更好地管理其资产…

外包干了9天,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;2018年我通过校招踏入了南京一家软件公司&#xff0c;开始了我的职业生涯。那时的我&#xff0c;满怀热血和憧憬&#xff0c;期待着在这个行业中闯出一片天地。然而&#xff0c;随着时间的推移&#xff0c;我发现自己逐渐陷入…

HarmonyOS NEXT应用开发—自定义日历选择器

介绍 本示例介绍通过CustomDialogController类显示自定义日历选择器。 效果图预览 使用说明 加载完成后显示主界面&#xff0c;点当前日期后会弹出日历选择器&#xff0c;选择日期后会关闭弹窗&#xff0c;主页面日期会变成选定的日期。 实现思路 获取当前月和下个月的日期…

技术资讯:Volar正式更名为Vue-Official

大家好&#xff0c;我是大澈&#xff01; 本文约700字&#xff0c;整篇阅读大约需要1分钟。 关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费加入问答群&#xff0c;一起交流技术难题与未来&#xff01; 现在关注公众号&#xff0c;免费送你 ”前后端入行大礼包“…

【智能算法】人工水母搜索算法(JS)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2020年&#xff0c;Chou 等人受到水母运动行为启发&#xff0c;提出了人工水母搜索算法(Artificial Jellyfish Search Optimizer, JS)。 2.算法原理 2.1算法思想 JS模拟了水母的搜索行为&#xf…

Halcon文件操作

1、Region读写操作 region&#xff08;区域&#xff09;是一种重要的数据类型&#xff0c;用于表示图像中的特定区域。这些区域可以代表图像中的目标、感兴趣的区域、边缘、形状等等 read_image (Image, printer_chip/printer_chip_01) dev_open_window (0, 0, 512, 512, black…

mysql: 如何开启慢查询日志?

1 确认慢查询日志功能已开启 执行以下sql语句&#xff0c;查看慢查询功能是否开启&#xff1a; show VARIABLES like slow_query_log;如果为ON&#xff0c;表示打开&#xff1b;如果为OFF&#xff0c;表示没有打开&#xff0c;需要开启慢查询功能。 执行以下sql语句&#xff0…

数据结构与算法----复习Part 15 ()

本系列是算法通关手册LeeCode的学习笔记 算法通关手册&#xff08;LeetCode&#xff09; | 算法通关手册&#xff08;LeetCode&#xff09; (itcharge.cn) 目录 一&#xff0c;二叉搜索树&#xff08;Binary Search Tree&#xff09; 二叉搜索树的查找 二叉搜索树的插入 …

java组合模式揭秘:如何构建可扩展的树形结构

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构以表示整体/部分层次结构。组合模式使得客户端可以统一对待单个对象和组合对象&#xff0c;从而使得客户端可以处理更复杂的结构。 组合模式的主要组成部分包括&…

Unity开发一个FPS游戏之二

在之前的文章中,我介绍了如何开发一个FPS游戏,添加一个第一人称的主角,并设置武器。现在我将继续完善这个游戏,打算添加敌人,实现其智能寻找玩家并进行对抗。完成的效果如下: fps_enemy_demo 下载资源 首先是设计敌人,我们可以在网上找到一些好的免费素材,例如在Unity…