从0到1构建微服务之分布式事务-Seata(七)

简介

1、Seata介绍

2、环境部署

2.1 下载

访问官网seata下载地址,下载相应的安装包,这里下载1.5.1版本
在这里插入图片描述

2.2 解压压缩包

将压缩包解压

2.3 配置seata的application.yml

进入到confi目录,找到application.yml进行编辑。这里主要是配置配置中心、注册中心以及存储。
本章选择nacos座位配置中心和注册中心,mysql为存储。配置如下:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${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

console:
  user:
    username: seata
    password: seata

seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace:
      group: SEATA_GROUP
      username:
      password:
      ##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:
      cluster: default
      username:
      password:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: root
      password: root
      min-conn: 5
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 100
      max-wait: 5000
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

2.4 创建数据库

我们选择了mysql作为我们的数据存储方式,那么需要启动mysql并创建一个名字为seata的库,接着需要创建三张表

  • global_table:全局事务
  • branch_table:分支事务
  • lock_table:全局锁

具体如下:
global_table记录了全局事务的信息,建表语句如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table`  (
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
  `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '事务ID',
  `status` tinyint(4) NOT NULL COMMENT '状态',
  `application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用ID',
  `transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '事务分组名',
  `transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '执行事务的方法',
  `timeout` int(11) NULL DEFAULT NULL COMMENT '超时时间',
  `begin_time` bigint(20) NULL DEFAULT NULL COMMENT '开始时间',
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用数据',
  `gmt_create` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`xid`) USING BTREE,
  INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
  INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

branch_table记录了分支事务的信息,建表语句如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for branch_table
-- ----------------------------
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table`  (
  `branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
  `xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
  `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '全局事务ID,不带TC地址',
  `resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源分组ID',
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源ID',
  `branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '事务模式,AT、XA等',
  `status` tinyint(4) NULL DEFAULT NULL COMMENT '状态',
  `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端ID',
  `application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用数据',
  `gmt_create` datetime(6) NULL DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime(6) NULL DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`branch_id`) USING BTREE,
  INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of branch_table
-- ----------------------------

SET FOREIGN_KEY_CHECKS = 1;

lock_table记录了锁相关的信息,建表语句如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table`  (
  `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '行键',
  `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '全局事务ID',
  `transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '全局事务ID,不带TC 地址',
  `branch_id` bigint(20) NOT NULL COMMENT '分支ID',
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源ID',
  `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名',
  `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主键对应的值',
  `gmt_create` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`row_key`) USING BTREE,
  INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

2.5 启动nacos

由于我们选择了nacos作为注册中心和配置中心,需要提前先启动

2.6 启动seata服务

进入到bin目录,双击seata-server.bat进行启动(这里是window演示)
在这里插入图片描述
登录nacos,查看服务注册情况
在这里插入图片描述

3、项目配置

3.1、 pom引入依赖

父类工程引入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>2.2.0.RELEASE</version>
    <exclusions>
        <!--版本较低,1.3.0,因此排除-->
        <exclusion>
            <artifactId>seata-spring-boot-starter</artifactId>
            <groupId>io.seata</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.5.1</version>
</dependency>

3.2、工程application.yml配置

只要是需要用到seata分布式事务的子工程,都需要在配置文件中添加seata配置,具体内容如下

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    # 参考tc服务自己的aaplcation.yml中的配置
    type: nacos
    nacos: # tc
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
      application: seata-server   # tc服务在nacos中的服务名称
      username:
      password:
  tx-service-group: seata-demo    # 事务组,根据这个获取tc服务的cluster名称
  #enable-auto-data-source-proxy: false  # 是否开启数据源代理
  service:
    vgroup-mapping:    # 事务组与TC服务cluster的映射关系
      seata-demo:   # 集群的名字
  data-source-proxy-mode: AT  # 开启数据源代理的 AT 模式,AT 也是默认模式

4、演示测试

项目介绍
首先回顾一下我们的项目结构
在这里插入图片描述

AT模式

AT工作模式工作机制
在这里插入图片描述

一阶段
1、将前后镜像数据以及业务 SQL 关的息成一条滚记录 (UNDO_LOG)
2、提交前,向TC注册分支,获取全局锁
3、本地事务提交,内容包括业务数据和UNDO_LOG记录,并将结果汇报给TC
二阶段-回滚:
1、收到回滚请求,开启本地事务
2、通过XID 和 Branch ID,找到UNDO LOG记录
3、进行数据校验,不通过则按照策略执行(关闭校验或手动介入)
4、生成滚sql并提交事务,然后上报给TC
二阶段-提交:
1、上报成功结果给TC,并异步批量删除UNDO LOG记录

AT工作模式演示
biz-admin调用user服务将用户id为1的用户名改为张三,再调用order服务将订单id为1的订单金额改为20,结果是可以正常修改。
在这里插入图片描述
在这里插入图片描述
biz-admin调用user服务将用户id为1的用户名改为李四,再调用order服务将订单id为1的订单金额改为30,此时发生了异常,结果是两张表依然是原数据。

XA模式

XA工作模式工作机制
在这里插入图片描述

执行阶段
1、开启全局事务、获取全局锁
2、各分支事务开启,提交sql,并将结果汇报给TC
完成阶段
各分支sql提交无异常,则将所有本地事务commit,否则rollback

XA工作模式演示

biz-admin调用user服务将用户id为1的用户名改为五,再调用order服务将订单d为1的订单金额改为50,修改成功
在这里插入图片描述
在这里插入图片描述

biz-admin调用user服务将用户id为1的用户名改为赵六,再调用order服务将订单id为1的订单金额改为60,此时发生了异常,修改不成功,结果依然是原数据

AT模式与XA模式对比

  • XA模式一阶段不提交事务,锁定资源;AT模式一阶直接提交,不锁定资源
  • XA模式依赖数据库机制实现回滚,AT利用数据快照(undo_log)实现数据回滚
  • XA模式强一致;AT式最终一致
  • 总结:
    XA模式强一致性,实现容易,性能差
    AT模式最终一致性,性能较好,会出现脏读,回滚异常需要人工介入

TCC模式

TCC模式工作机制
tcc 工作机制的差别在于需要自己准备三个接口,分别是锁定资源(try),确定接口(comfirm)以及取消接口
在这里插入图片描述

一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
二阶段 commit 行为:调用 自定义 的 commit 逻辑。
二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

SAGA模式

Saga模式工作机制
在这里插入图片描述

每个操作都需要相应的一个补偿操作,一旦某个环节失败,则往回执行所有的补偿操作,实现回滚
举例说明,补偿操作可以设计为:
1、订单服务: 取消订单
2、库存服务: 恢复库存
3、支付服务: 退款。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值