#|SpringCloud Alibaba 之Seata(总体第三篇)

一、Seata学习笔记 1、Seata概念 (1)什么是分布式事务

  • 是用处理分布式业务
  • 什么事务就不多说了呢
  • 那为什么要用分布式事务呢
    单库–> 分库分表–>多模块,分库分表
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    就是多个数据库要进行事务操作,我们无法人工干预,那就需要来这个seata来进行处理。
(2)Seata术语与分布式事务过程
  • 官网地址:tps://seata.io/zh-cn/
  • Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
  • 几个概念:分布式事务处理过程的一ID(全局唯一的id),三组件模型
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 分布式事务过程
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

(3)下载安装
  • 安装的1.0
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 修改file.conf
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    修改默认的名字【可以你自己设置名字】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    存储位置设置为db
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    新建seata数据库。
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    在seata里面执行seata的conf里面的数据库表,但是0.9版本后没有了【可以去官网上面找,或者下载0.9版,我选的后者因为之前下载过】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    如果实在不想下载的话,那就直接负债
-- 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(总体第三篇)
文章图片

#|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

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

  • 分别建三个数据库
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    CREATE DATABASE seata_order;
    CREATE DATABASE seata_storage;
    CREATE DATABASE seata_account;
    然后分别建表
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
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(总体第三篇)
文章图片

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、订单/库存/账号业务微服务 #|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

(1)建立订单模块Order-Module
  • 将项目
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 导入依赖
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: 2001spring: 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: 111feign: hystrix: enabled: falselogging: level: io: seata: infomybatis: mapperLocations: classpath:mapper/*.xml

  • 主启动
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 实体类
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 另外把你的seata里面的conf下的我们配置的两个文件拷贝到你项目的根目录里面。
  • DAO接口及实现
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

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(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    再来写我们的order
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 【#|SpringCloud Alibaba 之Seata(总体第三篇)】再来编写controller层
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 可以启动测试

(2)建立Storage-Module模块
  • 建立项目
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 导入依赖
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: 2002spring: 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: 111logging: level: io: seata: infomybatis: mapperLocations: classpath:mapper/*.xml

  • 主启动
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • dao
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • service层
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • controller
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • config配置
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • 主启动
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
(3)Account-Module模块 #|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

4、测试(添加相应注解) (1)查询一下数据库情况 #|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

#|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

#|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

(2)启动几个项目2001,2002,2003 #|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

  • 使用:http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100进行测试
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    此时发现数据库后端发生响应的增删改查,但是如果像下面这样进行延时处理
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    此时就报错了撒,
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    此时检查数据库,你不正常的处理都会增加,他们影响的是一圈,都影响了。
    然后写参数,name = “你自己想的名字”,rollbackFor = exception.class
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    页面看着是一样的,但是后台的数据库根本没有响应。
5、Seata原理 (1)再次回顾 #|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

建议使用1.0版本或之后。
#|SpringCloud Alibaba 之Seata(总体第三篇)
文章图片

  • TC就是我们启动的服务器
  • TM就是我们添加了@GlobalTransactional的就是TM,事务发起方
  • RM就是一个数据库,事务参与方。
  • 再次回顾处理过程
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

(2)AT模式
  • 采用的模式【默认用AT】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • AT第一阶段
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • AT第二阶段【成功提交】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
  • AT二阶段【失败回滚】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片
(3)打断点看原理
  • 没有什么服务启动的时候
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

  • 当开始我们的业务的时候看服务的brunch
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    我们的后端写的数据库修改的语句执行
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    这个里面就保存了前置镜像和后置的镜像【如果说到时候你的业务不能执行成功,那就要通过这里面的数据进行反向修改,把你的数据表还原到之前的状态】
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    这里就是你的TM数据库
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

    锁了哪些表
    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

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

    #|SpringCloud Alibaba 之Seata(总体第三篇)
    文章图片

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

    推荐阅读