「seata」分布式事务seata部署及应用

seata 版本

seata-server-2.0.0

一、部署seata服务

1、配置config.txt文件中的属性值

目录:seata-server-2.0.0\seata\script\config-center
在这里插入图片描述
修改的存储事务在数据库中
事务路由规则配置,仅针对客户端(重点和难点)

# 默认配置就行
service.vgroupMapping.default_tx_group=default
store.mode=db
store.lock.mode=db
store.session.mode=db

修改数据库配置

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&rewriteBatchedStatements=true
# 修改数据库用户名和密码
store.db.user=root
store.db.password=root123
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000

2、为seata服务单独创建一个nacos命名空间

在这里插入图片描述

命名空间名称:seata
命名空间ID:52b44c99-80b8-4902-8335-e1bf177e37ec
配置数:0 / 200
描述:分布式事务

3、利用脚本上传配置文件到nacos

前提条件:需要安装好git环境或者可以执行sh命令的运行环境
脚本目录:seata-server-2.0.0\seata\script\config-center\nacos
在这里插入图片描述
在窗口处执行命令:

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 	52b44c99-80b8-4902-8335-e1bf177e37ec -u nacos -w nacos

在这里插入图片描述
执行过程:
在这里插入图片描述
导入成功:
在这里插入图片描述
允许nacos界面如图所示(成功导入了118个配置项):
在这里插入图片描述

4、配置seata服务的application.yml

所在目录:seata-server-2.0.0\seata\conf\application.yml
在这里插入图片描述
在原有配置项上进行更改

# 完整的配置内容
server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash
# 控制台访问密码
# http://localhost:7091/
console:
  user:
    username: seata
    password: seata
# seata基础配置,启动的时候需要这些配置项
seata:
  # 配置中心
  config:
    type: nacos  # 配置中心类型为Nacos
    nacos:
      server-addr: 127.0.0.1:8848  # Nacos服务器地址
      group: SEATA_GROUP  # 配置文件所属的分组
      username: nacos  # Nacos用户名
      password: nacos  # Nacos密码
      namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec  # Nacos命名空间

  # 注册中心
  registry:
    type: nacos  # 注册中心类型为Nacos
    preferred-networks: 10.10.*  # 首选网络
    nacos:
      application: seata-server  # 应用名称
      server-addr: 127.0.0.1:8848  # Nacos服务器地址
      group: SEATA_GROUP  # 配置文件所属的分组
      username: nacos  # Nacos用户名
      password: nacos  # Nacos密码
      namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec  # Nacos命名空间

  # Seata服务器配置
  server:
    raft:
      group: default
      cluster:
      snapshot-interval: 600
      apply-batch: 32
      max-append-bufferSize: 262144
      max-replicator-inflight-msgs: 256
      disruptor-buffer-size: 16384
      election-timeout-ms: 1000
      reporter-enabled: false
      reporter-initial-delay: 60
      serialization: jackson
      compressor: none
      sync: true  # 日志和快照同步到磁盘
    service-port: 8091  # 服务端口
    max-commit-retry-timeout: -1
    max-rollback-retry-timeout: -1
    rollback-retry-timeout-unlock-enable: false
    enable-check-auth: true
    enable-parallel-request-handle: true
    enable-parallel-handle-branch: false
    retry-dead-threshold: 130000
    xaer-nota-retry-timeout: 60000
    enableParallelRequestHandle: true
    recovery:
      committing-retry-period: 1000
      async-committing-retry-period: 1000
      rollbacking-retry-period: 1000
      timeout-retry-period: 1000
    undo:
      log-save-days: 7
      log-delete-period: 86400000
    session:
      branch-async-queue-size: 5000  # 分支异步移除队列大小
      enable-branch-async-remove: false  # 启用分支会话的异步移除

  # 监控配置
  metrics:
    enabled: false  # 是否启用监控
    registry-type: compact
    exporter-list: prometheus
    exporter-prometheus-port: 9898  # Prometheus导出器端口

  # 传输配置
  transport:
    rpc-tc-request-timeout: 15000
    enable-tc-server-batch-send-response: false
    shutdown:
      wait: 3
    thread-factory:
      boss-thread-prefix: NettyBoss
      worker-thread-prefix: NettyServerNIOWorker
      boss-thread-size: 1

  # 安全配置
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017  # 密钥
    tokenValidityInMilliseconds: 1800000  # 令牌有效期(毫秒)
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**  # 忽略的URL列表

6、执行数据库脚本

脚本所在目录:seata-server-2.0.0\seata\script\server\db
全局事务会话信息由3块内容构成,全局事务-->分支事务-->全局锁,对应表global_table、branch_table、lock_table
在这里插入图片描述
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(1000),
    `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);

5、使用脚本启动seata服务

脚本所在目录:seata-server-2.0.0\seata\bin\seata-server.bat
在这里插入图片描述

二、配置并启动微服务

1、配置每个微服务的application.yml文件

一共有三个微服务,执行逻辑是:

  1. 创建新订单
  2. 扣减商品库存
  3. 从用户账户余额扣除金额

在三个微服务的application.yml文件中配置如下内容:

# 启用 Seata 分布式事务功能
seata:
  enabled: true
  # 启用自动数据源代理模式
  enable-auto-data-source-proxy: true
  # 事务组名称,用于标识相同应用下的不同事务服务,默认为 default_tx_group
  tx-service-group: default_tx_group
  # 数据源代理模式,指定为 XA 模式
  data-source-proxy-mode: XA
  # 注册中心配置
  registry:
    # 注册中心类型为 Nacos
    type: nacos
    nacos:
      # Nacos 服务器地址
      server-addr: 127.0.0.1:8848
      # Nacos 配置文件所属的分组
      group: SEATA_GROUP
      # 注册到 Nacos 的应用名称
      application: seata-server
      # Nacos 用户名
      username: nacos
      # Nacos 密码
      password: nacos
      # Nacos 命名空间
      namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec
  # 配置中心配置
  config:
    # 配置中心类型为 Nacos
    type: nacos
    nacos:
      # Nacos 服务器地址
      server-addr: 127.0.0.1:8848
      # Nacos 用户名
      username: nacos
      # Nacos 密码
      password: nacos
      # Nacos 配置文件所属的分组
      group: SEATA_GROUP
      # Nacos 命名空间
      namespace: 52b44c99-80b8-4902-8335-e1bf177e37ec

2、在每个微服务所在的数据库执行undo_log数据表结构

在每个微服务所在的数据库执行下面的回滚日志的SQL脚本

-- auto-generated definition
create table undo_log
(
    id            bigint auto_increment
        primary key,
    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,
    ext           varchar(100) null,
    constraint ux_undo_log
        unique (xid, branch_id)
)
    engine = InnoDB
    charset = utf8;

3、启动微服务向seata注册分支事务

三个微服务都启动之后会向seata服务注册分支事务,如下图所示:
在这里插入图片描述

三、模式解读

XA和AT的区别

简述AT模式与XA模式最大的区别是什么?

  • XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
  • XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
  • XA模式强一致;AT模式最终一致

执行逻辑代码如下:
在这里插入图片描述
他们之间的区别可以打断点查看,一个会立即提交事务一个不会。

1、XA模式

1.1 XA模式

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范
描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。

两阶段

XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。

正常情况:
在这里插入图片描述

异常情况:
在这里插入图片描述
一阶段:

  • 事务协调者通知每个事物参与者执行本地事务
  • 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁

二阶段:

  • 事务协调者基于一阶段的报告来判断下一步操作
    • 如果一阶段都成功,则通知所有事务参与者,提交事务
    • 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务

1.2 XA架构模型

Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:
在这里插入图片描述
RM一阶段的工作:

​ ① 注册分支事务到TC

​ ② 执行分支业务sql但不提交

​ ③ 报告执行状态到TC

TC二阶段的工作:

  • TC检测各分支事务执行状态

    a.如果都成功,通知所有RM提交事务

    b.如果有失败,通知所有RM回滚事务

RM二阶段的工作:

  • 接收TC指令,提交或回滚事务

1.3 XA的优缺点

XA模式的优点是什么?

  • 事务的强一致性,满足ACID原则。
  • 常用数据库都支持,实现简单,并且没有代码侵入

XA模式的缺点是什么?

  • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
  • 依赖关系型数据库实现事务

2、AT模式

1.1 AT模式

AT模式同样是分阶段提交的事务模型,不过弥补了XA模型中资源锁定周期过长的缺陷。

两阶段

阶段一RM的工作:

  • 注册分支事务
  • 记录undo-log(数据快照)
  • 执行业务sql并提交
  • 报告事务状态

阶段二提交时RM的工作:

  • 删除undo-log即可

阶段二回滚时RM的工作:

  • 根据undo-log恢复数据到更新前

1.2 AT架构模型

在这里插入图片描述

1.3 执行流程

AT模式下,当前分支事务执行流程如下:

一阶段:

1)TM发起并注册全局事务到TC
2)TM调用分支事务
3)分支事务准备执行业务SQL
4)RM拦截业务SQL,根据where条件查询原始数据,形成快照。
5)RM执行业务SQL,提交本地事务,释放数据库锁。此时 money = 90
6)RM报告本地事务状态给TC
二阶段:
1)TM通知TC事务结束
2)TC检查分支事务状态
​ a)如果都成功,则立即删除快照
​ b)如果有分支事务失败,需要回滚。读取快照数据({"id": 1, "money": 100}),将快照恢复到数据库。此时数据库再次恢复为100
流程图:
在这里插入图片描述

3、TCC模式

TCC和SAGA不做详细介绍

优缺点

TCC模式的每个阶段是做什么的?

  • Try:资源检查和预留
  • Confirm:业务执行和提交
  • Cancel:预留资源的释放

TCC的优点是什么?

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库

TCC的缺点是什么?

  • 有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦
  • 软状态,事务是最终一致
  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理

4、SAGA模式

TCC和SAGA不做详细介绍

优缺点

优点:

  • 事务参与者可以基于事件驱动实现异步调用,吞吐高
  • 一阶段直接提交事务,无锁,性能好
  • 不用编写TCC中的三个阶段,实现简单

缺点:

  • 软状态持续时间不确定,时效性差
  • 没有锁,没有事务隔离,会有脏写

相关推荐

  1. Seata分布式事务

    2024-04-12 16:54:03       40 阅读
  2. Seata分布式事务!!!

    2024-04-12 16:54:03       18 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-12 16:54:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-12 16:54:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-12 16:54:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-12 16:54:03       20 阅读

热门阅读

  1. 前端 Bundle Splitting 如何实现 详解

    2024-04-12 16:54:03       51 阅读
  2. 大模型推动机器人智能化的探索与实践

    2024-04-12 16:54:03       21 阅读
  3. 第六周学习笔记DAY.4-方法与方法重载

    2024-04-12 16:54:03       17 阅读
  4. LeetCode 213. 打家劫舍 II

    2024-04-12 16:54:03       14 阅读
  5. 排查linux系统是否被入侵

    2024-04-12 16:54:03       15 阅读
  6. 第九章-Broker-接收并处理生产者发送的消息

    2024-04-12 16:54:03       13 阅读
  7. python使用Flask框架开发API 配置远程访问

    2024-04-12 16:54:03       16 阅读