锋哥原创的分布式事务框架Seata视频教程:
实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)共计10条视频,包括:1 阿里分布式事务框架Seata简介、2 分布式事务简介、3 SpringCloud Alibaba分布式基础案例搭建等,UP主更多精彩视频,请关注UP账号。https://www.bilibili.com/video/BV1Uf4y1579F/seata主推的是AT模式强一致性解决方案,所以我们采用这个方案来解决前面案例的分布式问题。
7.1 下载和运行seata server
seata server地址:Releases · apache/incubator-seata · GitHub
最新版本 v1.4.2
我们用windows演示,下载seata-server-1.4.2.zip
seata-server配置文件:
seata server所有的配置都在conf文件夹内,该文件夹内有两个文件我们必须要详细介绍下。 seata server默认使用file(文件方式)进行存储事务日志、事务运行信息,我们可以通过-m db脚本参数的形式来指定,目前仅支持file、db这两种方式。
file.conf
该文件用于配置存储方式、透传事务信息的NIO等信息,默认对应registry.conf文件内的file方式配置。
registry.conf
seata server核心配置文件,可以通过该文件配置服务注册方式、配置读取方式。
注册方式目前支持file 、nacos 、eureka、redis、zk、consul、etcd3、sofa等方式,默认为file,对应读取file.conf内的注册方式信息。
读取配置信息的方式支持file、nacos 、apollo、zk、consul、etcd3等方式,默认为file,对应读取file.conf文件内的配置。
file.conf
我们加一个service
配置:
service {#vgroup->rgroup 服务分组 集群分组默认为"default"vgroupMapping.my_test_tx_group = "default"#only support single nodedefault.grouplist = "127.0.0.1:8091"#degrade current not support 服务降级达到多次错误不走seataenableDegrade = false#disabledisable = false#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanentmax.commit.retry.timeout = "-1"max.rollback.retry.timeout = "-1"
}
这里事务分组概念,我们最后单独讲,主要是为了集群故障的时候,能快速切换,实现高可用;
配置分组映射,集群分组再配置grouplist,暴露server地址,提供给seata-client调用;
最后我们运行bin目录下的seata-server.bat启动seata-server:
启动OK,监听端口8091
7.2 每个数据库都建一个undo_log回滚日志表
根据seata AT模式规范,我们新建undo_log表,db_account和db_order都要建;
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=3 DEFAULT CHARSET=utf8
7.3 项目里添加seata-client maven依赖
我们只需要在seata-common公共模块项目里添加seata依赖,其他子模块都有了,方便;
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
7.4 项目里配置seata分布式事务
首先是每个项目都要配置seata支持,请求seata-server,根据配置;
再通过@GlobalTransactional注解,开启全局分布式事务;
seata-order子项目 application.yml配置改下:
server:port: 8081servlet:context-path: /spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_order?serverTimezone=Asia/Shanghaiusername: rootpassword: 123456cloud:nacos:discovery:server-addr: 127.0.0.1:8848alibaba:seata:tx-service-group: my_test_tx_groupapplication:name: seata-ordermybatis:mapper-locations: classpath:mybatis/mapper/*.xmlseata:service:vgroup-mapping:my_test_tx_group: defaultgrouplist:default: 127.0.0.1:8091enable-degrade: falsedisable-global-transaction: false
主要多了服务分组和集群分组的配置:
同理,seata-account下的application.yml配置:
server:port: 8082servlet:context-path: /spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_account?serverTimezone=Asia/Shanghaiusername: rootpassword: 123456cloud:nacos:discovery:server-addr: 127.0.0.1:8848alibaba:seata:tx-service-group: my_test_tx_groupapplication:name: seata-accountmybatis:mapper-locations: classpath:mybatis/mapper/*.xmlseata:service:vgroup-mapping:my_test_tx_group: defaultgrouplist:default: 127.0.0.1:8091enable-degrade: falsedisable-global-transaction: false
seata-web下的application.yml配置:
server:port: 80servlet:context-path: /spring:cloud:nacos:discovery:server-addr: 127.0.0.1:8848alibaba:seata:tx-service-group: my_test_tx_groupapplication:name: seata-webseata:service:vgroup-mapping:my_test_tx_group: defaultgrouplist:java1234-seata-server: 127.0.0.1:8091enable-degrade: falsedisable-global-transaction: false
seata-web项目->WebController->shopping方法,添加@GlobalTransactional注解
7.5 分布式案例测试
三个子项目一起运行;
两个RM在seata-server注册成功;
seata-web项目的RM,TM注册成功;
seata-order项目的TM注册成功;
seata-account项目的TM注册成功;
我们用postman 发送 http://localhost/shopping
post请求
执行发现,订单表,和日志表都没有数据,说明测试OK;
7.6 setata二阶段提交过程剖析
因为是执行是一瞬间的,很多小伙伴根本无法感受到内部的二阶段提交过程。
-
一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
-
二阶段:
-
提交异步化,非常快速地完成。
-
回滚通过一阶段的回滚日志进行反向补偿。
-
所以我们在再seata-account项目里搞个断点,来看下回滚的一个流程;
seata-account项目debug启动;
再次postman测试,我们立刻查看db_order数据库表信息(比较难捕获,因为提交事务超时就立刻回滚,看不到信息)
订单服务执行完的时候,
db_order有数据
undo_log也有数据
说明一阶段业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
然后下面,如果提交事务超时或者有接口调用异常,则分支事务立刻根据回滚日志,立刻进行反向补偿,最后回滚日志会被清空;
如果接口调用一切正常,日志清空,全局事务提交,完成本次事务操作;