SpringCloud Alibaba之Seata分布式事务学习笔记(下)
2.2.2、服务集成seata组件实现全局分布式事务
三个服务都进行集成seata依赖,主要配置步骤如下:
1、引入seata依赖:
<!-- 引入seata依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
2、配置文件来添加seata配置项,下面给出三个服务的不同配置项,下面需要特别注意的就是黄线的部分需要根据不同的服务名来进行配置:
seata-user-service:
seata:
service:
vgroup-mapping:
# 这里需要对事务组做映射,默认的分组名为 应用名称-seata-service-group,将其映射到default集群
# 这个很关键,一定要配置对,不然会找不到服务
user-service-seata-service-group: default
grouplist:
default: localhost:8868
seata-book-service:
seata:
service:
vgroup-mapping:
# 这里需要对事务组做映射,默认的分组名为 应用名称-seata-service-group,将其映射到default集群
# 这个很关键,一定要配置对,不然会找不到服务
book-service-seata-service-group: default
grouplist:
default: localhost:8868
seata-borrow-service:
seata:
service:
vgroup-mapping:
# 这里需要对事务组做映射,默认的分组名为 应用名称-seata-service-group,将其映射到default集群
# 这个很关键,一定要配置对,不然会找不到服务
borrow-service-seata-service-group: default
grouplist:
default: localhost:8868
3、三个服务的启动器都去开启seata事务注解:
@EnableAutoDataSourceProxy //开启seata事务配置
4、在本地数据库中创建undo_log日志表
- 由于三个服务都使用的一个数据库seata-demo,所以我们直接在一个数据库中创建即可
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;
5、最终在我们要进行分布式事务的service方法中添加全局事务注解!也就是borrow-service服务中的borrow()方法:
@GlobalTransactional
2.2.3、测试
提前准备
首先将seata-server
服务器启动。
接着启动我们的三个服务:在启动时向seata-server
去进行注册
看下seata-server
服务的控制台:可以看到确实三个服务已经注册成功了
开始测试
首先来进行测试:http://localhost:8082/borrow/1/2
第一次借阅是没有问题的,看下数据库:
再次来进行借阅下:
ok,此时再看下数据库的各个表:原本在book表中产生问题的数据在这里就没有再出现了,可以看到中间出现异常能够成功回滚了
debug
我们在修改、删除操作上进行debug:
看下undo_log表:
扣减步骤完成后执行下一步:
再次看下undo_log表:
其中包含一个全局唯一xid:全局事务就是根据这一条记录来进行回滚管理的!
2.3、采用nacos模式服务
对于项目中引入依赖以及添加注解相关操作间2.2.2中的配置步骤,这里不再做演示。
2.3.1、配置完整步骤
1、在nacos中创建一个命名空间seata
2、修改配置文件
registry.conf:
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sof
type = "nacos"
nacos {
# 应用名固定为seata-server
application = "seata-server"
# 注册中心的地址
serverAddr = "127.0.0.1:8848"
# 默认
group = "SEATA_GROUP"
# 命名空间的id
namespace = "c30eb1d8-8e49-4b5d-beca-b1bf9479e94a"
# 默认
cluster = "default"
# 连接用户名与密码
username = "nacos"
password = "nacos"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = "c30eb1d8-8e49-4b5d-beca-b1bf9479e94a"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
dataId = "seataServer.properties"
}
}
3、下载develop包,执行其中的script中脚本来对nacos的配置中心中seata命名空间配置项进行初始化:
下载地址:seata开发包
链接:https://pan.baidu.com/s/1iiQphUPbvgcIyXcIjUcjZA
提取码:cbr2
进入到其中nacos目录下执行脚本,在windows中我们使用git工具来使用:
./nacos-config-interactive.sh
最终效果如下:
4、手动在命名空间seata中添加三个服务的配置项:
service.vgroupMapping.user-service-seata-service-group SEATA_GROUP default
service.vgroupMapping.book-service-seata-service-group SEATA_GROUP default
service.vgroupMapping.borrow-service-seata-service-group SEATA_GROUP default
5、在三个服务项目中的各个服务添加配置项(替换之前的file模式):
# 2、nacos模式
seata:
# 注册
registry:
# 使用Nacos
type: nacos
nacos:
# 使用Seata的命名空间,这样才能正确找到Seata服务,由于组使用的是SEATA_GROUP,配置默认值就是,就不用配了
namespace: c30eb1d8-8e49-4b5d-beca-b1bf9479e94a
username: nacos
password: nacos
# 配置
config:
type: nacos
nacos:
namespace: c30eb1d8-8e49-4b5d-beca-b1bf9479e94a
username: nacos
password: nacos
6、关于nacos-server的会话存储位置(默认是file)
此时注册和配置相关的会话都继承在Nacos中进行了
还可以配置一下事务会话信息的存储方式,默认是file类型,那么就会在运行目录下创建file_store
目录,可以看下启动seata-server后创建的文件效果:
6.1、其实我们可以将其搬到数据库中存储,只需要修改一下配置即可,在seata的命名空间中进行修改配置内容如下:
- 1、修改两个配置:
store.session.mode
、``store.mode的值为
db` - 2、接着我们对数据库信息进行一下配置:
- 数据库驱动(8.0的需要修改):
com.mysql.cj.jdbc.Driver
- 数据库URL:默认就是seata数据库就好。
- 数据库用户名密码:
store.db.user
、store.db.password
- 数据库驱动(8.0的需要修改):
6.2、创建一个数据库【seata】:
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`status` TINYINT NOT NULL,
`application_id` VARCHAR(32),
`transaction_service_group` VARCHAR(255),
`transaction_name` VARCHAR(128),
`timeout` INT,
`begin_time` BIGINT,
`application_data` VARCHAR(2000),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR(256),
`branch_type` VARCHAR(8),
`status` TINYINT,
`client_id` VARCHAR(64),
`application_data` VARCHAR(2000),
`gmt_create` DATETIME(6),
`gmt_modified` DATETIME(6),
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(128),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `distributed_lock`
(
`lock_key` CHAR(20) NOT NULL,
`lock_value` VARCHAR(20) NOT NULL,
`expire` BIGINT,
primary key (`lock_key`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('HandleAllSession', ' ', 0);
那么配置就已经完成了!
2.3.2、测试
前提准备
启动nacos服务、seata服务如下:
执行seata启动的命令:
seata-server.bat -p 8868
启动三个服务:
与此同时,可以看到在seata服务的控制台中你可以看到里面的服务注册信息:
测试
访问借阅地址:http://localhost:8082/borrow/1/2
再此访问,肯定在中途去判断是否该用户借阅了书阶段出现异常,进行回滚,我们只需要关注book表中的书籍借阅数量有没有-1的问题,其实就是看其有没有回滚:
看下数据库:
没有问题!
2.3.3、debug
在这里我们来进行打上断点:
看看seata数据库以及我们自己本身的数据库undo_log中的记录是否产生变化:
接着来了一个请求,我们看debug的目前阶段:
此时来看数据库的情况:
seata数据库:记录依次是红框从上往下
seata-demo中的undo_log表:
可以看到用户表中的xid是依赖于tc也就是seata-server来进行回滚的。
参考资料
- 点赞
- 收藏
- 关注作者
评论(0)