alibaba seata1.2.0 分布式事务服务端安装配置,图解AX事务,spring boot 2.0现实AT, 图解TCC事务

一、概述

在微服务架构下,虽然我们会尽量避免分布式事务,但是只要业务复杂的情况下这是一个绕不开的问题,如何保证业务数据一致性呢?本文主要介绍同步场景下使用Seata的AT模式来解决一致性问题。
Seata是 阿里巴巴 开源的 一站式分布式事务解决方案 中间件,以 高效 并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题

二、Seata介绍

seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

优缺点:

  • Seata的解决方案是两阶段提交的升级版,传统两阶段提交资源管理器(RM)放在数据库端,由数据库管理,需要数据库支持XA协议。
  • 而Seata把RM从数据库端以jar包的形式移到了应用端,剥离了数据库对XA协议的要求。
  • Seata认为我们对数据库的提交操作90%以上都是成功的,所以我们可以节省XA协议锁定资源的时间,应用层执行完直接提交就可以释放锁,如果出错需要回滚则锁定到回滚完成
  • 所以Seata减少了事务对资源的锁定时间,提高了并发和吞吐量

三、Seata下载

由于seata主要是做分布式事务的, 服务端地址如下
https://github.com/seata/seata/releases
打开版本地址如下
在这里插入图片描述

3.2 目录结构

在这里插入图片描述

3.3 配置文件如何配置

先配置file.conf

在这里插入图片描述
关于readme 说明
在这里插入图片描述

配置模式,设置mysql

在这里插入图片描述

我这里是mysql 5.6版本, 如果是mysql 8的版本 这里的url 连接需要修改

在 lib/jdbc 里面查看存在的jar包
在这里插入图片描述

如果需要使用mysql 8的jar 包 需要修改url 连接,并且设置时区

代码如下

jdbc:mysql://192.168.1.188:3306/seata?serverTimezone=Asia/Shanghai

服务端脚本地址
https://github.com/seata/seata/tree/develop/script/server

#### 里面存放的sql 脚本, 本人用的mysql 数据库 脚本如下
-- -------------------------------- 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;

执行mysql 完成后效果图

在这里插入图片描述

现在配置service

在这里插入图片描述
代码如下

service {
  #交易服务组映射 的组名称必须要与客户端一致 my_test_tx_group  seata-server必须要与registrt.conf 一致
  #transaction service group mapping
  vgroupMapping.my_test_tx_group = "seata-server"
  #only support when registry.type=file, please don't set multiple addresses
  #这里设置ip, 一般不用改
  default.grouplist = "127.0.0.1:8091"
  #disable seata
  disableGlobalTransaction = false
}

现在file.conf 文件配置完成,效果图如下
在这里插入图片描述

配置 registry.conf 文件

在这里插入图片描述

  1. eureka 配置
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "eureka"  # 修改这里,这里我使用的时eureka注册中心,对应下面的eureka配置,其他的配置信息可删除


  ## 修改这里,因为上面用的是eureka,需要配置下面的eureka注册信息
  eureka {
    serviceUrl = "http://localhost:9000/eureka"
    application = "seata-server"
    weight = "1"
  }
  
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  # 这里使用file的配置文件,其余的可以删除掉
  type = "file"


  # 使用conf下的file.conf配置
  file {
    name = "file.conf"
  }
 }
  1. nacos 配置
registry {
  type = "nacos"

  nacos {
    serverAddr = "nacos"
    namespace = ""
  }
}

config {
  type = "nacos"

  nacos {
    serverAddr = "nacos"
    namespace = ""
  }
}

现在服务端配置基本完成,现在打开服务端

在这里插入图片描述
启动效果图
在这里插入图片描述
在这里插入图片描述

术语:
TC 事务协调者

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

TM 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务

RM 资源管理器

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

关于seata 支持的事务说明

关于AT模式

AT 模式下,把每个数据库被当做是一个 Resource,Seata 里称为 DataSource Resource。业务通过 JDBC 标准接口访问数据库资源时,Seata 框架会对所有请求进行拦截,做一些操作。每个本地事务提交时,Seata RM(Resource Manager,资源管理器) 都会向 TC(Transaction Coordinator,事务协调器) 注册一个分支事务。当请求链路调用完成后,发起方通知 TC 提交或回滚分布式事务,进入二阶段调用流程。此时,TC 会根据之前注册的分支事务回调到对应参与者去执行对应资源的第二阶段。TC 是怎么找到分支事务与资源的对应关系呢?每个资源都有一个全局唯一的资源 ID,并且在初始化时用该 ID 向 TC 注册资源。在运行时,每个分支事务的注册都会带上其资源 ID。这样 TC 就能在二阶段调用时正确找到对应的资源。
这就是我们的 AT 模式。简单总结一下,就是把每个数据库当做一个 Resource,在本地事务提交时会去注册一个分支事务
AT模式的核心是对业务无侵入,是一种改进后的两阶段提交,其设计思路

以一个示例来说明:

两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。

tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。 tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁 。

在这里插入图片描述
tx1 二阶段全局提交,释放 全局锁 。tx2 拿到 全局锁 提交本地事务。

在这里插入图片描述
如果 tx1 的二阶段全局回滚,则 tx1 需要重新获取该数据的本地锁,进行反向补偿的更新操作,实现分支的回滚。

此时,如果 tx2 仍在等待该数据的 全局锁,同时持有本地锁,则 tx1 的分支回滚会失败。分支的回滚会一直重试,直到 tx2 的 全局锁 等锁超时,放弃 全局锁 并回滚本地事务释放本地锁,tx1 的分支回滚最终成功。

因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的,所以不会发生 脏写 的问题。

spring boot2.0x 显示的核心代码

首先在main方面启动类增加 @EnableAutoDataSourceProxy
在这里插入图片描述
services 提供的全局的事务注解
@GlobalTransactional 开启全局事务
在这里插入图片描述

seata TCC(Try-Confirm-Cancel)模式

Seata 框架把每组 TCC 接口当做一个 Resource,称为 TCC Resource。这套 TCC 接口可以是 RPC,也以是服务内 JVM 调用。在业务启动时,Seata 框架会自动扫描识别到 TCC 接口的调用方和发布方。如果是 RPC 的话,就是 sofa:reference、sofa:service、dubbo:reference、dubbo:service 等。
扫描到 TCC 接口的调用方和发布方之后。如果是发布方,会在业务启动时向 TC 注册 TCC Resource,与 DataSource Resource 一样,每个资源也会带有一个资源 ID。
如果是调用方,Seata 框架会给调用方加上切面,与 AT 模式一样,在运行时,该切面会拦截所有对 TCC 接口的调用。每调用一次 Try 接口,切面会先向 TC 注册一个分支事务,然后才去执行原来的 RPC 调用。当请求链路调用完成后,TC 通过分支事务的资源 ID 回调到正确的参与者去执行对应 TCC 资源的 Confirm 或 Cancel 方法。
在讲完了整个框架模型以后,大家可能会问 TCC 三个接口怎么实现。因为框架本身很简单,主要是扫描 TCC 接口,注册资源,拦截接口调用,注册分支事务,最后回调二阶段接口。最核心的实际上是 TCC 接口的实现逻辑。下面我将根据蚂蚁金服内部多年的实践来为大家分析怎么实现一个完备的 TCC 接口。
在这里插入图片描述

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读