一、Seata学习笔记 1、Seata概念 (1)什么是分布式事务
- 是用处理分布式业务
- 什么事务就不多说了呢
- 那为什么要用分布式事务呢
单库–> 分库分表–>多模块,分库分表
文章图片
文章图片
文章图片
就是多个数据库要进行事务操作,我们无法人工干预,那就需要来这个seata来进行处理。
- 官网地址:tps://seata.io/zh-cn/
- Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
- 几个概念:分布式事务处理过程的一ID(全局唯一的id),三组件模型
文章图片
- 分布式事务过程
文章图片
文章图片
- 安装的1.0
文章图片
- 修改file.conf
文章图片
修改默认的名字【可以你自己设置名字】
文章图片
存储位置设置为db
文章图片
文章图片
新建seata数据库。
文章图片
在seata里面执行seata的conf里面的数据库表,但是0.9版本后没有了【可以去官网上面找,或者下载0.9版,我选的后者因为之前下载过】
文章图片
如果实在不想下载的话,那就直接负债
-- 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】
文章图片
文章图片
- 启动:先启动nacos,再启动seata,好家伙,我启动报错,大概原因就是我们的mysql8,而0.9和1.0版本【我测试过的两个版本】不支持mysql8,所以你有两种选择,要么就自己换数据库,要么跟我一样换为1.3版本,然后进上面的配置,然后加上如下的配置。
文章图片
文章图片
- 分别建三个数据库
文章图片
CREATE DATABASE seata_order;
CREATE DATABASE seata_storage;
CREATE DATABASE seata_account;
然后分别建表
文章图片
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;
然后分别到三个库下面去执行如下的数据库
文章图片
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
- 将项目
文章图片
- 导入依赖
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
- 主启动
文章图片
- 实体类
文章图片
文章图片
- 另外把你的seata里面的conf下的我们配置的两个文件拷贝到你项目的根目录里面。
- DAO接口及实现
文章图片
文章图片
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,这里写的是去调用另外两个微服务的名称
文章图片
文章图片
文章图片
再来写我们的order
文章图片
- 【#|SpringCloud Alibaba 之Seata(总体第三篇)】再来编写controller层
文章图片
文章图片
文章图片
- 可以启动测试
- 建立项目
文章图片
- 导入依赖
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
- 主启动
文章图片
- dao
文章图片
文章图片
- service层
文章图片
文章图片
- controller
文章图片
- config配置
文章图片
文章图片
- 主启动
文章图片
文章图片
4、测试(添加相应注解) (1)查询一下数据库情况
文章图片
文章图片
文章图片
(2)启动几个项目2001,2002,2003
文章图片
- 使用:http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100进行测试
文章图片
此时发现数据库后端发生响应的增删改查,但是如果像下面这样进行延时处理
文章图片
此时就报错了撒,
文章图片
此时检查数据库,你不正常的处理都会增加,他们影响的是一圈,都影响了。
然后写参数,name = “你自己想的名字”,rollbackFor = exception.class
文章图片
文章图片
页面看着是一样的,但是后台的数据库根本没有响应。
文章图片
建议使用1.0版本或之后。
文章图片
- TC就是我们启动的服务器
- TM就是我们添加了@GlobalTransactional的就是TM,事务发起方
- RM就是一个数据库,事务参与方。
- 再次回顾处理过程
文章图片
- 采用的模式【默认用AT】
文章图片
- AT第一阶段
文章图片
- AT第二阶段【成功提交】
文章图片
- AT二阶段【失败回滚】
文章图片
文章图片
- 没有什么服务启动的时候
文章图片
- 当开始我们的业务的时候看服务的brunch
文章图片
我们的后端写的数据库修改的语句执行
文章图片
这个里面就保存了前置镜像和后置的镜像【如果说到时候你的业务不能执行成功,那就要通过这里面的数据进行反向修改,把你的数据表还原到之前的状态】
文章图片
这里就是你的TM数据库
文章图片
锁了哪些表
文章图片
- 如果成功
它就会删除相应的几张回滚表
文章图片
文章图片
- 如果失败
就根据你那个那个字段进行回滚反向执行。
推荐阅读
- Hadoop|HDFS 巡检
- Rest-assured|Rest-assured1- 测试框架
- SpringQueryMap 这个注解一不小心就采坑了
- java|Nginx,一看就会
- spring|项目总结 -谷粒学院
- 分布式服务下,消息中间件改造
- 一文看懂Spring Bean注解!莫要再被各种“注解”搞晕了!
- Java Map接口详解
- KubeVirt with YRCloudFile 擦出创新的火花