分布式事务组件Seata简介与使用,搭配Nacos统一管理服务端和客户端配置

devtools/2025/2/3 19:12:02/

文章目录

  • 一. Seata简介
  • 二. 官方文档
  • 三. Seata分布式事务代码实现
    • 0. 环境简介
    • 1. 添加undo_log表
    • 2. 添加依赖
    • 3. 添加配置
    • 4. 开启Seata事务管理
    • 5. 启动演示
  • 四. Seata Server配置Nacos
    • 1. 修改配置类型
    • 2. 创建Nacos配置
  • 五. Seata Client配置Nacos
    • 1. 增加Seata关联Nacos的配置
    • 2. 在Nacos中对应的train-group添加配置
    • 3. 测试有效性

一. Seata简介

Seata 是一款开源的分布式事务解决方案,旨在解决微服务架构下的数据一致性问题。它支持 AT、TCC、Saga 和 XA 四种事务模式,能够适应不同的业务场景。

  • AT模式,默认,简单,需要增加undo_log表,生成反向SQL,性能高;回滚后,原来没数据的,现在还是没数据
  • TCC模式,try confirm/cancel,三个阶段的代码都得自己实现,Seata只负责调度;对业务代码侵入性较强,必要时可能还要修改数据库
  • SAGA模式,长事务解决方案,需要程序员自己编写两阶段代码(AT模式不需要写第二阶段);基于状态机来实现的,需要一个JSON文件,可异步执行
  • XA模式,XA 协议是由 X/Open 组织提出的分布式事务处理规范,基于数据库的XA协议来实现2PC发称为XA方案,适用于强一致性的场景,比如金融、银行等

Seata 的核心架构包括事务协调器(TC)、事务管理器(TM)和资源管理器(RM),通过两阶段提交协议实现全局事务的管理。其优势在于对业务代码侵入性低、性能高效,且与 Spring Cloud、Dubbo 等主流微服务框架无缝集成,是构建高可靠分布式系统的理想选择。

二. 官方文档

官方文档
下载地址
GitHub 仓库
Seata 示例项目

三. Seata分布式事务代码实现

接下来将用代码模拟AT模式的分布式事务管理。

0. 环境简介

项目模拟12306会员购票场景,购票后需要进行余票更新以及会员购票信息保存的操作,分别对应business模块和member模块的操作。要求business通过feign调用member的保存功能。

此时如果用传统事务注解@Transactional,仅仅在business模块的方法进行事务管理,是无法管理远程调用的模块同样进行回滚的。

此时就要用到Seata进行分布式事务管理,同时演示的是AT模式,自动生成反向SQL。

1. 添加undo_log表

businessmember数据库中添加undo_log表,执行SQL:

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;

2. 添加依赖

businessmember模块中添加Seata依赖:

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

3. 添加配置

businessmember模块的bootstrap.properties添加配置:

# 事务组名称service.vgroupMapping.train-group=default
seata.tx-service-group=train-group
# 事务组和seata集群做关联
seata.service.vgroup-mapping.train-group=default
# seata集群对应的机器
seata.service.grouplist.default=127.0.0.1:8091

一个项目的多个模块,配置成同一个事务组

4. 开启Seata事务管理

仅需要service业务逻辑方法上添加注解,即可开启Seata事务管理:

java">import io.seata.spring.annotation.GlobalTransactional;@GlobalTransactional

5. 启动演示

  • 启动Seata服务
    解压Seata文件夹,双击bin目录下的seata-server.bat
    在这里插入图片描述
    在这里插入图片描述

Seata服务可视化界面启动在7091端口,而监听端口是8091

  • 启动SpringBoot服务
    在这里插入图片描述

在这里插入图片描述

可以看到启动后Seata打印的日志,表明SpringBoot应用和Seata成功连接,成功注册两个TM和RM

  • 异常设置
    为了显示事务回滚效果,在member模块保存的业务逻辑中,手动添加事务异常:
java">    public void save(MemberTicketReq req) throws Exception {LOG.info("seata全局事务ID save: {}", RootContext.getXID());DateTime now = DateTime.now();Ticket ticket = BeanUtil.copyProperties(req, Ticket.class);ticket.setId(SnowUtil.getSnowflakeNextId());ticket.setCreateTime(now);ticket.setUpdateTime(now);ticketMapper.insert(ticket);// 模拟被调用方出现异常if (1 == 1) {throw new Exception("测试异常11");}}

预计效果为,Seata回滚余票更新,并向前端抛出异常

  • 测试结果
    在这里插入图片描述
    在这里插入图片描述

与预期结果相同,测试成功!

四. Seata Server配置Nacos

让Nacos统一设置Seata Server的配置,以免再去手动修改配置文件。

nacos的介绍和使用可以参考我之前的博客:传送门

1. 修改配置类型

  • 打开配置文件seata\conf\application.yml,修改以下内容:
seata:config:# support: nacos, consul, apollo, zk, etcd3type: fileregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: file

更改为nacos的注册中心和配置中心:

seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 127.0.0.1:8848namespace: traingroup: SEATA_GROUPusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:data-id: seataServer.propertiesregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: traincluster: defaultusername: nacospassword: nacoscontext-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:

!!! 注意每个:后面都要空一格
namespace: 设置nacos中的命名空间,用于项目间隔离
group:nacos中分组名称
username和password:nacos的用户名和密码,默认都为nacos

  • 重启Seata服务
    在这里插入图片描述

可见配置已生效,注册服务成功。登录Nacos客户端也可以看到配置的服务:
在这里插入图片描述

2. 创建Nacos配置

  • 创建本地数据库seata:
    在seata数据库中执行以下sql语句,创建四张表:
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(`xid`                       VARCHAR(128) NOT NULL,`transaction_id`            BIGINT,`status`                    TINYINT      NOT NULL,`application_id`            VARCHAR(32),`transaction_service_group` VARCHAR(32),`transaction_name`          VARCHAR(128),`timeout`                   INT,`begin_time`                BIGINT,`application_data`          VARCHAR(2000),`gmt_create`                DATETIME,`gmt_modified`              DATETIME,PRIMARY KEY (`xid`),KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(`branch_id`         BIGINT       NOT NULL,`xid`               VARCHAR(128) NOT NULL,`transaction_id`    BIGINT,`resource_group_id` VARCHAR(32),`resource_id`       VARCHAR(256),`branch_type`       VARCHAR(8),`status`            TINYINT,`client_id`         VARCHAR(64),`application_data`  VARCHAR(2000),`gmt_create`        DATETIME(6),`gmt_modified`      DATETIME(6),PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(128),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;CREATE TABLE IF NOT EXISTS `distributed_lock`
(`lock_key`       CHAR(20) NOT NULL,`lock_value`     VARCHAR(20) NOT NULL,`expire`         BIGINT,primary key (`lock_key`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
  • 新建配置如下:
    在这里插入图片描述
store.mode=db
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/seata?rewriteBatchedStatements=true
store.db.user=seata
store.db.password=seata

数据库、用户名和密码需要修改为自己的

这样就成功利用Nacos管理Seata的服务端配置了!

五. Seata Client配置Nacos

接下来还需要用Nacos管理Seata的客户端配置。

1. 增加Seata关联Nacos的配置

在Seata管理的模块的bootstrap.properties中添加Nacos配置:

# seata注册中心,要和seata server的application.yml配置保持一致
seata.registry.type=nacos
seata.registry.nacos.application=seata-server
seata.registry.nacos.server-addr=127.0.0.1:8848
seata.registry.nacos.group=SEATA_GROUP
seata.registry.nacos.namespace=train
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos# seata配置中心,要和seata server的application.yml配置保持一致
seata.config.type=nacos
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.group=SEATA_GROUP
seata.config.nacos.namespace=train
seata.config.nacos.dataId=seataServer.properties
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos# 事务组名称,必须在nacos中有配置过:service.vgroupMapping.train-group=default
seata.tx-service-group=train-group

2. 在Nacos中对应的train-group添加配置

在这里插入图片描述

service.vgroupMapping.train-group=default
service.default.grouplist=127.0.0.1:8091

解释:
原来这两行是在SpringBoot中配置的,而现在配置了Seata+Nacos,等于是Nacos统一管理配置了,不用在本地一处处修改了,只要在线上统一管理即可。而在本地仅需要配置事务组名称即可,简化了配置。

3. 测试有效性

还是手动抛出异常,查看是否回滚:
在这里插入图片描述

成功回滚,则线上配置生效


http://www.ppmy.cn/devtools/155807.html

相关文章

vue3中customRef的用法以及使用场景

1. 基本概念 customRef 是 Vue3 提供的用于创建自定义响应式引用的 API&#xff0c;允许显式地控制依赖追踪和触发响应。它返回一个带有 get 和 set 函数的工厂函数来自定义 ref 的行为。 1.1 基本语法 import { customRef } from vuefunction createCustomRef(value) {retu…

Linux之内存管理前世今生(一)

一个程序&#xff08;如王者荣耀&#xff09;平常是存储在硬盘上的&#xff0c;运行时才把这个程序载入内存&#xff0c;CPU才能执行。 问题&#xff1a; 这个程序载入内存的哪个位置呢&#xff1f;载入内核所在的空间吗&#xff1f;系统直接挂了。 一、虚拟内存 1.1 内存分…

OSCP 渗透测试:网络抓包工具的使用指南

在 OSCP 考试和渗透测试中&#xff0c;网络数据分析是至关重要的技能。无论是嗅探明文密码、分析恶意流量&#xff0c;还是溯源攻击&#xff0c;抓包工具都是我们的得力助手。 本文将介绍 OSI 七层网络模型 及其在网络分析中的作用&#xff0c;并详细讲解 Wireshark 和 tcpdum…

【Pytest】生成html报告中,中文乱码问题解决方案

链接上一篇文章:https://blog.csdn.net/u013080870/article/details/145369926?spm1001.2014.3001.5502 中文乱码问题&#xff0c;python3&#xff0c;Python3.7后&#xff0c;还一个文件就是result.py 因为中文可以在内容中&#xff0c;也可能在文件名&#xff0c;类名&…

Git 常用命令汇总

# 推荐一个十分好用的git插件---->GitLens 其实很多命令操作完全界面化了&#xff0c;鼠标点点就可以实现但是命令是必要的&#xff0c;用多了你就知道了 Git 常用命令汇总 1. Git 基础操作 命令作用git init初始化本地仓库git clone <repo-url>克隆远程仓库到本地g…

论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策

1.论文链接&#xff1a;Bayesian, Systems-based, Multilevel Analysis of Associations for Complex Phenotypes: from Interpretation to Decision 摘要&#xff1a; 遗传关联研究&#xff08;GAS&#xff09;报告的结果相对稀缺&#xff0c;促使许多研究方向。尽管关联概念…

【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(二)

目录 1 -> HML语法 1.1 -> 页面结构 1.2 -> 数据绑定 1.3 -> 普通事件绑定 1.4 -> 冒泡事件绑定5 1.5 -> 捕获事件绑定5 1.6 -> 列表渲染 1.7 -> 条件渲染 1.8 -> 逻辑控制块 1.9 -> 模板引用 2 -> CSS语法 2.1 -> 尺寸单位 …

全面解析文件上传下载删除漏洞:风险与应对

在数字化转型的时代&#xff0c;文件上传、下载与删除功能已经成为各类应用程序的标准配置&#xff0c;从日常办公使用的协同平台&#xff0c;到云端存储服务&#xff0c;再到社交网络应用&#xff0c;这些功能在给用户带来便捷体验、显著提升工作效率的同时&#xff0c;也隐藏…