Alibaba Seata 学习日记(AT 模式详解)

本文详细介绍了Alibaba Seata的AT模式,包括其无入侵式特点、两阶段提交机制以及具体实现步骤。内容涵盖Seata TC协调者的搭建、使用Nacos作为配置中心,以及AT模式代码的编写。通过示例展示了AT模式如何实现分布式事务的提交和回滚,强调了其对业务的无入侵性。
摘要由CSDN通过智能技术生成

Alibaba Seata 学习日记(AT 模式详解)

AT 模式详解

AT 模式的特点就是对业务无入侵式,整体机制分二阶段提交。

  • 两阶段提交协议的演变。
    • 一阶段 : 业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。也就是对事物和 undo_log 直接进行提交,然后释放本地资源
    • 二阶段 :
      • 提交异步化,非常快速地完成。如果提交只需要删除 回滚日志和事物表中的数据即可
      • 回滚通过一阶段的回滚日志进行反向补偿。如果回滚,需要按照回滚日志表中的数据进行反向的补偿,来达到回滚的目的

在AT 模式下,用户只需关注自己的 业务 SQL,用户的业务 SQL 作为第一阶段, Seata 框架回自动生成事物的二阶段提交和回滚操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odRrWuGI-1625326389680)(https://www.it235.com/assets/img/image-20210215181643407.c55e8abc.png)]

Seata 具体实现步骤

  1. Transaction Manager(事物管理器)使用 @GlobalTransaction 进行全局事务开启、提交、回滚
  2. Transaction Manager 开始 RPC 调用远程服务。
  3. Resource Manager 端 seata-client 通过扩展 DataSourceProxy,实现自动生成 UNDO_LOG 于 TC 上报。
  4. Transaction Manager 告知 Transaction Coordinator 提交/回滚全局事务
  5. Transaction Coordinator 通知 Resource Manager 各自致性 commit/rollback 操作,同时清除 undo_log。

在这里插入图片描述

搭建 Seata TC 协调者

1.点击此处下载最新版本,并解压缩

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K8DjpgKO-1625326389683)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625220112945.png)

  1. 修改 conf/file.conf 文件

    • 将 mode=“file” 修改为 mode=“db”

      ## transaction log store, only used in seata-server
      store {
        ## store mode: file、db、redis
        mode = "db"
      
        ## file store property
        file {
          ## store location dir
          dir = "sessionStore"
          # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
          maxBranchSessionSize = 16384
          # globe session size , if exceeded throws exceptions
          maxGlobalSessionSize = 512
          # file buffer size , if exceeded allocate new buffer
          fileWriteBufferCacheSize = 16384
          # when recover batch read size
          sessionReloadReadSize = 100
          # async, sync
          flushDiskMode = async
        }
      
        ## database store property
        db {
          ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
          datasource = "druid"
          ## mysql/oracle/postgresql/h2/oceanbase etc.
          dbType = "mysql"
          driverClassName = "com.mysql.jdbc.Driver"
          url = "jdbc:mysql://192.168.192.128:3306/seata"
          user = "root"
          password = "123456"
          minConn = 5
          maxConn = 100
          globalTable = "global_table"
          branchTable = "branch_table"
          lockTable = "lock_table"
          queryLimit = 100
          maxWait = 5000
        }
      
        ## redis store property
        redis {
          host = "127.0.0.1"
          port = "6379"
          password = ""
          database = "0"
          minConn = 1
          maxConn = 10
          maxTotal = 100
          queryLimit = 100
        }
      
      }
      
      
    • 数据库对应上述配置新建seata的DB,并分配给指定的用户权限

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbwe9r3M-1625326389684)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625220727082.png)

    • 初始化 table, 注意此处一定要初始化,并且 1.0 之后的版本没有 sql 脚本,这里贴出

      -- the table to store GlobalSession datadrop table if exists `global_table`;create table `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`));-- the table to store BranchSession datadrop table if exists `branch_table`;create table `branch_table` (  `branch_id` bigint not null,  `xid` varchar(128) not null,  `transaction_id` bigint ,  `resource_group_id` varchar(32),  `resource_id` varchar(256) ,  `lock_key` varchar(128) ,  `branch_type` varchar(8) ,  `status` tinyint,  `client_id` varchar(64),  `application_data` varchar(2000),  `gmt_create` datetime,  `gmt_modified` datetime,  primary key (`branch_id`),  key `idx_xid` (`xid`));-- the table to store lock datadrop table if exists `lock_table`;create table `lock_table` (  `row_key` varchar(128) not null,  `xid` varchar(96),  `transaction_id` long ,  `branch_id` long,  `resource_id` varchar(256) ,  `table_name` varchar(32) ,  `pk` varchar(36) ,  `gmt_create` datetime ,  `gmt_modified` datetime,  primary key(`row_key`));-- the table to store seata xid data-- 0.7.0+ add context-- you must to init this sql for you business databese. the seata server not need it.-- 此脚本必须初始化在你当前的业务数据库中,用于AT 模式XID记录。与server端无关(注:业务数据库)-- 注意此处0.3.0+ 增加唯一索引 ux_undo_logdrop table `undo_log`;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;
      
    • 初始化后的3张表如下

      在这里插入图片描述

    1. 修改 registry.conf 文件

      这个文件内容分为 registry 和 config 2部分,我们使用之前学过的 nacos 注册中心,你也可以采用默认的 file 方式。

      • registryconfig 部分由 type=“file” 都换成 type=“nacos” (注意是2处地方)

      • 将 2 处的 nacos 配置根据实际情况需要调整参数,本机启动 nacos 则不需要调整

        registry {
                   # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa  type = "nacos"  loadBalance = "RandomLoadBalance"  loadBalanceVirtualNodes = 10  nacos {
                     application = "seata-server"    serverAddr = "127.0.0.1:8848"    group = "SEATA_GROUP"    namespace = ""    cluster = "default"    username = "nacos"    password = "nacos"  }  eureka {
                     serviceUrl = "http://localhost:8761/eureka"    application = "default"    weight = "1"  }  redis {
                     serverAddr = "localhost:6379"    db = 0    password = ""    cluster = "default"    timeout = 0  }  zk {
                     cluster = "default"    serverAddr = "127.0.0.1:2181"    sessionTimeout = 6000    connectTimeout = 2000    username = ""    password = ""  }  consul {
                     cluster = "default"    serverAddr = "127.0.0.1:8500"  }  etcd3 {
                     cluster = "default"    serverAddr = "http://localhost:2379"  }  sofa {
                     serverAddr = "127.0.0.1:9603"    application = "default"    region = "DEFAULT_ZONE"    datacenter = "DefaultDataCenter"    cluster = "default"    group = "SEATA_GROUP"    addressWaitTime = "3000"  }  file {
                     name = "file.conf"  }}config {
                   # file、nacos 、apollo、zk、consul、etcd3  type = "nacos"  nacos {
                     serverAddr = "127.0.0.1:8848"    namespace = ""    group = "SEATA_GROUP"    username = "nacos"    password = "nacos"  }  consul {
                     serverAddr = "127.0.0.1:8500"  }  apollo {
                     appId = "seata-server"    apolloMeta = "http://192.168.1.204:8801"    namespace = "application"    apolloAccesskeySecret = ""  }  zk {
                     serverAddr = "127.0.0.1:2181"    sessionTimeout = 6000    connectTimeout = 2000    username = ""    password = ""  }  etcd3 {
                     serverAddr = "http://localhost:2379"  }  file {
                     name = "file.conf"  }}
        
    2. 修改 conf/logback.xml 的文件(可选操作)

          <property name="LOG_HOME" value="../logs/seata"/>
      
    3. 双击 bin/seata-server.bat 文件启动服务(有可能出现闪退)

    4. 为了方便更加清晰的日志,建议使用 cmd 的方式。

      • 打开 cmd 窗口,使用 cd 命令切换到 seatabin目录
      • 输入 seata-server.bat 回车
    5. 启动成功的结果如下

      在这里插入图片描述

使用 nacos 作为 Seata 的配置中心

思考

如果不用 Nacos, 那 Seata 的默认配置中心在哪?

我们编辑 registry.conf 找到 config 部分,内容如下:

config {  # file、nacos 、apollo、zk、consul、etcd3  type = "file"  nacos {    ......  }  consul {    ......  }  apollo {    ......  }  zk {    ......  }  etcd3 {    ......  }  -- 重点  file {    name = "file.conf"  }}

就是 file.conf 文件,接下来我们不再依靠文件而是 nacos,要让 seata 使用 nacos 作为配置中心,我们需要按照以下步骤进行操作。

  1. 保证你的 nacos 服务已经启动,且可正常连接。

  2. 添加命名空间,获取 namespace 的 id, 这里是 ead46517-79ec-4396-909a-13b09563de93

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42XTnk6e-1625326389686)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625224107541.png)

  3. 修改 registry.conf 文件中的 registry 部分type=“nacos”,同时修改 nacos 部分的配置

    nacos {    serverAddr = "127.0.0.1:8848"    namespace = "ead46517-79ec-4396-909a-13b09563de93"    group = "SEATA_GROUP"    username = "nacos"    password = "nacos"  }
    
  4. 修改 registry.conf 文件中的 config 部分type=“nacos”,同时修改 nacos 部分的配置

    nacos {    serverAddr = "127.0.0.1:8848"    namespace = "ead46517-79ec-4396-909a-13b09563de93"    group = "SEATA_GROUP"    username = "nacos"    password = "nacos"  }
    
  5. 下载nacos-config.脚本config.txt点击进入下载页

    • nacos-config.sh 和 nacos-config.py 选择一个:在 seata 目录下新建 script 目录,将 nacos-config.sh 放入 script 目录下

    • config.txt : 该文件存放在 seata 目录下,与 conf、lib 目录同级, seata 的非常全的配置内容,可以通过 nacos-config.sh 脚本推送到 nacos 配置中心

    • 修改 config.txt 的内容,下述 1 处暂时无需修改, 2处需要换成你的 DB 连接路径

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-21Qr5Vnc-1625326389686)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625225302229.png)

    • 打开 git bashlinux 类命令行,执行 sh 脚本 (注意脚本释放有执行的权限)

      # -h 主机,你可以使用localhost,-p 端口号 你可以使用8848,-t 命名空间ID,-u 用户名,-w 密码$ sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t ead46517-79ec-4396-909a-13b09563de93 -u nacos -w nacos
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FDrMBMa4-1625326389687)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625225845189.png)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wF5Z6BqE-1625326389688)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625225859701.png)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfgAV0Qt-1625326389688)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625225933298.png)

编写 AT 模式代码

Resource Manager 实现

  1. 创建订单和库存服务的DB

    -- 库存服务DB执行CREATE TABLE `tab_storage` (                               `id` bigint(11) NOT NULL AUTO_INCREMENT,                               `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',                               `total` int(11) DEFAULT NULL COMMENT '总库存',                               `used` int(11) DEFAULT NULL COMMENT '已用库存',                               PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;INSERT INTO `tab_storage` (`product_id`, `total`,`used`)VALUES ('1', '96', '4');INSERT INTO `tab_storage` (`product_id`, `total`,`used`)VALUES ('2', '100','0');-- 订单服务DB执行CREATE TABLE `tab_order` (                             `id` bigint(11) NOT NULL AUTO_INCREMENT,                             `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',                             `product_id` bigint(11) DEFAULT NULL COMMENT '产品id',                             `count` int(11) DEFAULT NULL COMMENT '数量',                             `money` decimal(11,0) DEFAULT NULL COMMENT '金额',                             `status` int(1) DEFAULT NULL COMMENT '订单状态:0:创建中;1:已完成',                             PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oS3MKNAU-1625326389688)(Alibaba Seata 学习日记(AT 模式详解)].assets/image-20210625230817562.png)

  2. 各数据库加入 undo_log 表

    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;
    
  3. 添加 seata pom.xml 依赖

    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <packaging>pom</packaging>    <modules>        <module>demo01</module>    </modules>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.3.2.RELEASE</version>        <relativePath/>    </parent>    <groupId>com.xssh.seata</groupId>    <artifactId>seata-parent</artifactId>    <version>1.0.0-SNAPSHOT</version>    <name>seata-parent</name>    <description>seata演示demo</description>    <properties>        <java.version>1.8</java.version>    </properties></project>
    
    <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <packaging>pom</packaging>    <modules>        <module>demo01</module>    </modules>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.3.2.RELEASE
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值