已删除用户
发布于 2023-07-30 / 1 阅读 / 0 评论 / 0 点赞

Seata分布式事务

1、 事务简介

事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。

在关系数据 库中,一个事务由一组SQL语句组成。事务应该具有4个属性:【原子性、一致性、隔离性、持久性】。 这四个属性通常称为ACID特性。

2、在JDBC编程中,我们通过java.sql.Connection对象来开启、关闭或者提交事务。代码如下所 示

Connection conn = ... //获取数据库连接
2 conn.setAutoCommit(false); //开启事务
3 try{
4    //...执行增删改查sql
5    conn.commit(); //提交事务
6 }catch (Exception e) {
7   conn.rollback();//事务回滚
8 }finally{
9    conn.close();//关闭链接
10 }

3 、Transational     声明式事务  

大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务 (Local Transaction)。本地事务的ACID特性是数据库直接提供支持。

4、如果遇见以下情况。【跨库事务、分库分表、服务化】 需要用到分布式事务

  Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B 又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要 不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。

分布式事务

  • 什么是分布式事务:

指一次大的操作由不同的小操作组成的,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

  • 常见的解决方案(seata、消息队列、XA、saga)

    分布式事务Seata

  • 中文官网:https://seata.io/zh-cn/

  • seata 是一款分布式事务的解决方案、是阿里开源的一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

seata将为用户提供了 【AT 、TCC、SAGA、和AX 】事务模式

  • AT----在数据库层面 需要加入行级锁 一种无侵入的分布式事务解决方案。

在第一阶段,seata会拦截业务SQL,首先解析SQL 语义,找到业务SQL 要更新的业务数据,在业务数据被更新前,将其保存成 before image 然后执行sql 更新业务语句,在业务数据更新之后,将其在保存到 after image 最后生成行锁,以上操作全部在一个数据库事务内完成,这样保证了一阶段的原子性。
在第二阶段,如果是提交的话,因为业务sql 在第一级段已经执行,只要删除 before image 和 after image 和行锁
在第二阶段回滚、before image 保存最初的数据 逆向sql 数据还原。 删除before image 删除 after image 删除行锁
  • TCC---在业务层面 侵入性比较强 编写代码较多 没有锁的概念 性能强

  • TCC 模式需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作;事务发起方在一阶 段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。

    try (){

  • sendMQ

  • }

  • confirm(){

  • } 数据入库 cancel 回滚

  • SAGA:

  • AX:

2、2pc(两个阶段)

Prepare :

1. 询问--- 协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应。

2. 执行-- 各个参与者接收到协调者事务请求后,执行事务操作(例如更新一个关系型数据库表中的记录),并将  Undo 和 Redo 信息记录事务日志中。

3. 响应 如果参与者成功执行了事务并写入 Undo 和 Redo 信息,则向协调者返回 YES 响应,否则返回 NO  响应。当然,参与者也可能宕机,从而不会返回响应

commit:

1、commit 请求 协调者向所有参与者发送 Commit 请求。

2. 事务提交 参与者收到 Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。

3. 反馈结果 参与者执行事务提交后向协调者发送 Ack 响应。

4. 完成事务 接收到所有参与者的 Ack 响应后,完成事务提交。

TC 事务协调者

维护全局和分支事务的状态,驱动全局事务提交和回滚

TM 事务管理器

开启全局事务,配合事务协调者提交或回滚

RM 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

  • 分布式事务Seata在微服务中的应用

    • 快速搭建Seata服务 环境

    技术栈: springboot + mysql5.7以上 + nacos

  • 1、新建mysql 数据库 seata_server

    -- -------------------------------- 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_gmt_modified_status` (`gmt_modified`, `status`),
        KEY `idx_transaction_id` (`transaction_id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8;
    
    -- 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 = utf8;
    
    -- the table to store lock data
    CREATE TABLE IF NOT EXISTS `lock_table`
    (
        `row_key`        VARCHAR(128) NOT NULL,
        `xid`            VARCHAR(96),
        `transaction_id` BIGINT,
        `branch_id`      BIGINT       NOT NULL,
        `resource_id`    VARCHAR(256),
        `table_name`     VARCHAR(32),
        `pk`             VARCHAR(36),
        `gmt_create`     DATETIME,
        `gmt_modified`   DATETIME,
        PRIMARY KEY (`row_key`),
        KEY `idx_branch_id` (`branch_id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8;

    下载客户端的资源目录 : https://seata/script at 1.3.0 · seata/seata · GitHub

  • client 存放client端sql脚本,参数配置

  • config-center 各个配置中心参数导入脚本,config.txt(包含server和client,原名nacos-config.txt)为通用参数文件

  • server server端数据库脚本及各个容器配置

    db存储模式+Nacos(注册&配置中心)部署 

配置

1、数据库配置

2、注册中心配置

3、naocs 配置中心 文件配置

讲config.txt 文件导入到nacos 中 nacos 有脚本文件可以执行导入

4、启动

sh ${SEATAPATH}/script/config‐center/nacos/nacos‐config.sh ‐h localhost ‐p 8848 ‐g SEATA_GROUP ‐t 5a3c7d6c‐f497‐ 4d68‐a71a‐2e5e3340b3ca
-h: host,默认值 localhost
-p: port,默认值 8848
-g: 配置分组,默认值为 'SEATA_GROUP'
-t: 租户信息,对应 Nacos 的命名空间ID字段, 默认值为空 

快速搭建Seata 客户端环境

1、导入Seata 依赖

<dependency>
3 <groupId>com.alibaba.cloud</groupId>
4 <artifactId>spring‐cloud‐starter‐alibaba‐seata</artifactId>
5 </dependency>

2、每个服务都需要交建立以下表

 CREATE TABLE `undo_log` (
2 `id` bigint(20) NOT NULL AUTO_INCREMENT,
3 `branch_id` bigint(20) NOT NULL,
4 `xid` varchar(100) NOT NULL,
5 `context` varchar(128) NOT NULL,
6 `rollback_info` longblob NOT NULL,
7 `log_status` int(11) NOT NULL,
8 `log_created` datetime NOT NULL,
9 `log_modified` datetime NOT NULL,
10 PRIMARY KEY (`id`),
11 UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

3、修改application.yml配置
4、在需要的地方需要添加@GlobalTransactional注解


评论