当前位置: 首页 > article >正文

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

文章目录

  • 一. 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事务管理:

import io.seata.spring.annotation.GlobalTransactional;


@GlobalTransactional

5. 启动演示

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

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

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

在这里插入图片描述

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

  • 异常设置
    为了显示事务回滚效果,在member模块保存的业务逻辑中,手动添加事务异常:
    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, etcd3
    type: file
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: file

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

seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: train
      group: SEATA_GROUP
      username: nacos
      password: nacos
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: train
      cluster: default
      username: nacos
      password: nacos
      context-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 = InnoDB
  DEFAULT 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 = InnoDB
  DEFAULT 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 = InnoDB
  DEFAULT 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 = InnoDB
  DEFAULT 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.db-type=mysql
store.db.driver-class-name=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.kler.cn/a/529192.html

相关文章:

  • 全覆盖路径规划-精准细胞覆盖算法
  • QT知识点复习
  • GenAI 在金融服务领域的应用:2025 年的重点是什么
  • OVS-DPDK
  • 高速稳定,功能强大的免费下载工具!!
  • AJAX笔记入门篇
  • 【华为OD-E卷 - 报数游戏 100分(python、java、c++、js、c)】
  • doris:JSON导入数据
  • Games104——引擎工具链基础
  • Python的那些事第八篇:Python中的类与对象
  • MusicFree-开源的第三方音乐在线播放和下载工具, 支持歌单导入[对标落雪音乐]
  • Nginx知识
  • 什么是Javascript,有什么特点
  • 【cocos官方案例改】跳跃牢猫
  • 【VUE】简述Vue中mixin、extends 的覆盖逻辑
  • NLP深度学习 DAY5:Sequence-to-sequence 模型详解
  • MySQL复制扩展功能
  • AI基本概念之——张量(Tensor)
  • 遗传算法与深度学习实战(33)——WGAN详解与实现
  • 小巧免费,本地视频播放器MPC-BE
  • 理解 InnoDB 如何处理崩溃恢复
  • Java小白入门教程:Object
  • 一个 windows 自动语音识别案列
  • 我用Ai学Android Jetpack Compose之LazyColumn
  • 【LLM-agent】(task2)用llama-index搭建AI Agent
  • Miniconda 安装及使用