SpringCloud Alibaba 之Seata(总体第三篇)

一、Seata学习笔记

1、Seata概念

(1)什么是分布式事务

  • 是用处理分布式业务
  • 什么事务就不多说了呢
  • 那为什么要用分布式事务呢
    单库–> 分库分表–>多模块,分库分表
    SpringCloud Alibaba 之Seata(总体第三篇)_第1张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第2张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第3张图片
    就是多个数据库要进行事务操作,我们无法人工干预,那就需要来这个seata来进行处理。

(2)Seata术语与分布式事务过程

  • 官网地址:tps://seata.io/zh-cn/

  • Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。

  • 几个概念:分布式事务处理过程的一ID(全局唯一的id),三组件模型
    SpringCloud Alibaba 之Seata(总体第三篇)_第4张图片

  • 分布式事务过程
    在这里插入图片描述
    SpringCloud Alibaba 之Seata(总体第三篇)_第5张图片

(3)下载安装

  • 安装的1.0
    SpringCloud Alibaba 之Seata(总体第三篇)_第6张图片

  • 修改file.conf
    SpringCloud Alibaba 之Seata(总体第三篇)_第7张图片
    修改默认的名字【可以你自己设置名字】
    SpringCloud Alibaba 之Seata(总体第三篇)_第8张图片
    存储位置设置为db
    SpringCloud Alibaba 之Seata(总体第三篇)_第9张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第10张图片
    新建seata数据库。
    SpringCloud Alibaba 之Seata(总体第三篇)_第11张图片
    在seata里面执行seata的conf里面的数据库表,但是0.9版本后没有了【可以去官网上面找,或者下载0.9版,我选的后者因为之前下载过】
    SpringCloud Alibaba 之Seata(总体第三篇)_第12张图片
    如果实在不想下载的话,那就直接负债

-- the table to store GlobalSession data
drop 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 data
drop 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 data
drop 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`)
);

然后再修改配置文件【改为db】
SpringCloud Alibaba 之Seata(总体第三篇)_第13张图片
SpringCloud Alibaba 之Seata(总体第三篇)_第14张图片

  • 启动:先启动nacos,再启动seata,好家伙,我启动报错,大概原因就是我们的mysql8,而0.9和1.0版本【我测试过的两个版本】不支持mysql8,所以你有两种选择,要么就自己换数据库,要么跟我一样换为1.3版本,然后进上面的配置,然后加上如下的配置。
    SpringCloud Alibaba 之Seata(总体第三篇)_第15张图片

2、准备业务数据库

SpringCloud Alibaba 之Seata(总体第三篇)_第16张图片

  • 分别建三个数据库
    SpringCloud Alibaba 之Seata(总体第三篇)_第17张图片
    CREATE DATABASE seata_order;
    CREATE DATABASE seata_storage;
    CREATE DATABASE seata_account;
    然后分别建表
    SpringCloud Alibaba 之Seata(总体第三篇)_第18张图片
USE seata_order;
CREATE TABLE t_order(
    id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    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已完结'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;

SELECT * FROM t_order;


USE seata_storage;
CREATE TABLE t_storage(
    id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    product_id BIGINT(11) DEFAULT NULL COMMENT '产品id',
    total INT(11) DEFAULT NULL COMMENT '总库存',
    used INT(11) DEFAULT NULL COMMENT '已用库存',
    residue INT(11) DEFAULT NULL COMMENT '剩余库存'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;
INSERT INTO t_storage(id, product_id, total, used, residue) VALUES(1,1,100,0,100);
SELECT * FROM t_storage;


USE seata_account;
CREATE TABLE t_account(
    id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    user_id BIGINT(11) DEFAULT NULL COMMENT '用户id',
    total DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',
    used DECIMAL(10,0) DEFAULT NULL COMMENT '已用额度',
    residue DECIMAL(10,0) DEFAULT 0 COMMENT '剩余可用额度'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;
INSERT INTO t_account(id, user_id, total, used, residue) VALUES(1,1,1000,0,1000);
SELECT * FROM t_account;

然后分别到三个库下面去执行如下的数据库
SpringCloud Alibaba 之Seata(总体第三篇)_第19张图片

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)建立订单模块Order-Module

  • 将项目
    SpringCloud Alibaba 之Seata(总体第三篇)_第20张图片

  • 导入依赖

 
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-seata
            
        
        
            io.seata
            seata-all
            1.3.0
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            mysql
            mysql-connector-java
            8.0.22
        
        
            com.alibaba
            druid-spring-boot-starter
            1.1.10
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.0.0
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.projectlombok
            lombok
            true
        
    
  • 写yaml
server:
  port: 2001

spring:
  application:
    name: seata-order-service
  cloud:
    alibaba:
      seata:
        #自定义事务组名称需要与seata-server中的对应
        tx-service-group: fsp_tx_group
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 111

feign:
  hystrix:
    enabled: false

logging:
  level:
    io:
      seata: info

mybatis:
  mapperLocations: classpath:mapper/*.xml
  • 主启动
    SpringCloud Alibaba 之Seata(总体第三篇)_第21张图片

  • 实体类
    SpringCloud Alibaba 之Seata(总体第三篇)_第22张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第23张图片

  • 另外把你的seata里面的conf下的我们配置的两个文件拷贝到你项目的根目录里面。

  • DAO接口及实现
    SpringCloud Alibaba 之Seata(总体第三篇)_第24张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第25张图片






    
        
        
        
        
        
        
    

    
        insert into t_order (id,user_id,product_id,count,money,status)
        values (null,#{userId},#{productId},#{count},#{money},0);
    


    
        update t_order set status = 1
        where user_id=#{userId} and status = #{status};
    


  • 我们在这里也要写另外两个模块的service,这里写的是去调用另外两个微服务的名称
    SpringCloud Alibaba 之Seata(总体第三篇)_第26张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第27张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第28张图片
    再来写我们的order
    SpringCloud Alibaba 之Seata(总体第三篇)_第29张图片

  • 再来编写controller层
    SpringCloud Alibaba 之Seata(总体第三篇)_第30张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第31张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第32张图片

  • 可以启动测试

(2)建立Storage-Module模块

  • 建立项目
    SpringCloud Alibaba 之Seata(总体第三篇)_第33张图片

  • 导入依赖


        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-seata
            
                
                    seata-all
                    io.seata
                
            
        
        
            io.seata
            seata-all
            1.3.0
        
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.0.0
        
        
            mysql
            mysql-connector-java
            5.1.37
        
        
            com.alibaba
            druid-spring-boot-starter
            1.1.10
        
        
            org.projectlombok
            lombok
            true
        
    
  • yaml
server:
  port: 2002

spring:
  application:
    name: seata-storage-service
  cloud:
    alibaba:
      seata:
        tx-service-group: fsp_tx_group
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 111

logging:
  level:
    io:
      seata: info

mybatis:
  mapperLocations: classpath:mapper/*.xml
  • 主启动
    SpringCloud Alibaba 之Seata(总体第三篇)_第34张图片
  • dao
    SpringCloud Alibaba 之Seata(总体第三篇)_第35张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第36张图片
  • service层
    SpringCloud Alibaba 之Seata(总体第三篇)_第37张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第38张图片
  • controller
    SpringCloud Alibaba 之Seata(总体第三篇)_第39张图片
  • config配置
    SpringCloud Alibaba 之Seata(总体第三篇)_第40张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第41张图片
  • 主启动
    SpringCloud Alibaba 之Seata(总体第三篇)_第42张图片

(3)Account-Module模块

SpringCloud Alibaba 之Seata(总体第三篇)_第43张图片

4、测试(添加相应注解)

(1)查询一下数据库情况

SpringCloud Alibaba 之Seata(总体第三篇)_第44张图片
SpringCloud Alibaba 之Seata(总体第三篇)_第45张图片
SpringCloud Alibaba 之Seata(总体第三篇)_第46张图片

(2)启动几个项目2001,2002,2003

SpringCloud Alibaba 之Seata(总体第三篇)_第47张图片

  • 使用:http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100进行测试
    SpringCloud Alibaba 之Seata(总体第三篇)_第48张图片
    此时发现数据库后端发生响应的增删改查,但是如果像下面这样进行延时处理
    SpringCloud Alibaba 之Seata(总体第三篇)_第49张图片
    此时就报错了撒,
    SpringCloud Alibaba 之Seata(总体第三篇)_第50张图片
    此时检查数据库,你不正常的处理都会增加,他们影响的是一圈,都影响了。
    然后写参数,name = “你自己想的名字”,rollbackFor = exception.class
    SpringCloud Alibaba 之Seata(总体第三篇)_第51张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第52张图片
    页面看着是一样的,但是后台的数据库根本没有响应。

5、Seata原理

(1)再次回顾

在这里插入图片描述
建议使用1.0版本或之后。
SpringCloud Alibaba 之Seata(总体第三篇)_第53张图片

  • TC就是我们启动的服务器

  • TM就是我们添加了@GlobalTransactional的就是TM,事务发起方

  • RM就是一个数据库,事务参与方。

  • 再次回顾处理过程
    SpringCloud Alibaba 之Seata(总体第三篇)_第54张图片

(2)AT模式

  • 采用的模式【默认用AT】
    SpringCloud Alibaba 之Seata(总体第三篇)_第55张图片
  • AT第一阶段
    SpringCloud Alibaba 之Seata(总体第三篇)_第56张图片
  • AT第二阶段【成功提交】
    SpringCloud Alibaba 之Seata(总体第三篇)_第57张图片
  • AT二阶段【失败回滚】
    在这里插入图片描述
    SpringCloud Alibaba 之Seata(总体第三篇)_第58张图片

(3)打断点看原理

  • 没有什么服务启动的时候
    SpringCloud Alibaba 之Seata(总体第三篇)_第59张图片

  • 当开始我们的业务的时候看服务的brunch
    SpringCloud Alibaba 之Seata(总体第三篇)_第60张图片
    我们的后端写的数据库修改的语句执行
    SpringCloud Alibaba 之Seata(总体第三篇)_第61张图片
    这个里面就保存了前置镜像和后置的镜像【如果说到时候你的业务不能执行成功,那就要通过这里面的数据进行反向修改,把你的数据表还原到之前的状态】
    SpringCloud Alibaba 之Seata(总体第三篇)_第62张图片
    这里就是你的TM数据库
    SpringCloud Alibaba 之Seata(总体第三篇)_第63张图片
    锁了哪些表
    在这里插入图片描述

  • 如果成功
    它就会删除相应的几张回滚表SpringCloud Alibaba 之Seata(总体第三篇)_第64张图片
    SpringCloud Alibaba 之Seata(总体第三篇)_第65张图片

  • 如果失败
    就根据你那个那个字段进行回滚反向执行。

你可能感兴趣的