文章目录
简介
1、Seata介绍
2、环境部署
2.1 下载
访问官网seata下载地址,下载相应的安装包,这里下载1.5.1版本
2.2 解压压缩包
将压缩包解压
2.3 配置seata的application.yml
进入到confi目录,找到application.yml进行编辑。这里主要是配置配置中心、注册中心以及存储。
本章选择nacos座位配置中心和注册中心,mysql为存储。配置如下:
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace:
group: SEATA_GROUP
username:
password:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key: ""
#secret-key: ""
data-id: seataServer.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace:
cluster: default
username:
password:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key: ""
#secret-key: ""
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
user: root
password: root
min-conn: 5
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 100
max-wait: 5000
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
2.4 创建数据库
我们选择了mysql作为我们的数据存储方式,那么需要启动mysql并创建一个名字为seata的库,接着需要创建三张表
- global_table:全局事务
- branch_table:分支事务
- lock_table:全局锁
具体如下:
global_table记录了全局事务的信息,建表语句如下:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for global_table
-- ----------------------------
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
`xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
`transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '事务ID',
`status` tinyint(4) NOT NULL COMMENT '状态',
`application_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用ID',
`transaction_service_group` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '事务分组名',
`transaction_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '执行事务的方法',
`timeout` int(11) NULL DEFAULT NULL COMMENT '超时时间',
`begin_time` bigint(20) NULL DEFAULT NULL COMMENT '开始时间',
`application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用数据',
`gmt_create` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`xid`) USING BTREE,
INDEX `idx_gmt_modified_status`(`gmt_modified`, `status`) USING BTREE,
INDEX `idx_transaction_id`(`transaction_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
branch_table记录了分支事务的信息,建表语句如下:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for branch_table
-- ----------------------------
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table` (
`branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
`xid` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
`transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '全局事务ID,不带TC地址',
`resource_group_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源分组ID',
`resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源ID',
`branch_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '事务模式,AT、XA等',
`status` tinyint(4) NULL DEFAULT NULL COMMENT '状态',
`client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端ID',
`application_data` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用数据',
`gmt_create` datetime(6) NULL DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime(6) NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`branch_id`) USING BTREE,
INDEX `idx_xid`(`xid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of branch_table
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
lock_table记录了锁相关的信息,建表语句如下:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
`row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '行键',
`xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '全局事务ID',
`transaction_id` bigint(20) NULL DEFAULT NULL COMMENT '全局事务ID,不带TC 地址',
`branch_id` bigint(20) NOT NULL COMMENT '分支ID',
`resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源ID',
`table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名',
`pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主键对应的值',
`gmt_create` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`row_key`) USING BTREE,
INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
SET FOREIGN_KEY_CHECKS = 1;
2.5 启动nacos
由于我们选择了nacos作为注册中心和配置中心,需要提前先启动
2.6 启动seata服务
进入到bin目录,双击seata-server.bat进行启动(这里是window演示)
登录nacos,查看服务注册情况
3、项目配置
3.1、 pom引入依赖
父类工程引入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.0.RELEASE</version>
<exclusions>
<!--版本较低,1.3.0,因此排除-->
<exclusion>
<artifactId>seata-spring-boot-starter</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.5.1</version>
</dependency>
3.2、工程application.yml配置
只要是需要用到seata分布式事务的子工程,都需要在配置文件中添加seata配置,具体内容如下
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
# 参考tc服务自己的aaplcation.yml中的配置
type: nacos
nacos: # tc
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
application: seata-server # tc服务在nacos中的服务名称
username:
password:
tx-service-group: seata-demo # 事务组,根据这个获取tc服务的cluster名称
#enable-auto-data-source-proxy: false # 是否开启数据源代理
service:
vgroup-mapping: # 事务组与TC服务cluster的映射关系
seata-demo: # 集群的名字
data-source-proxy-mode: AT # 开启数据源代理的 AT 模式,AT 也是默认模式
4、演示测试
项目介绍
首先回顾一下我们的项目结构
AT模式
AT工作模式工作机制
一阶段
1、将前后镜像数据以及业务 SQL 关的息成一条滚记录 (UNDO_LOG)
2、提交前,向TC注册分支,获取全局锁
3、本地事务提交,内容包括业务数据和UNDO_LOG记录,并将结果汇报给TC
二阶段-回滚:
1、收到回滚请求,开启本地事务
2、通过XID 和 Branch ID,找到UNDO LOG记录
3、进行数据校验,不通过则按照策略执行(关闭校验或手动介入)
4、生成滚sql并提交事务,然后上报给TC
二阶段-提交:
1、上报成功结果给TC,并异步批量删除UNDO LOG记录
AT工作模式演示
biz-admin调用user服务将用户id为1的用户名改为张三,再调用order服务将订单id为1的订单金额改为20,结果是可以正常修改。
biz-admin调用user服务将用户id为1的用户名改为李四,再调用order服务将订单id为1的订单金额改为30,此时发生了异常,结果是两张表依然是原数据。
XA模式
XA工作模式工作机制
执行阶段:
1、开启全局事务、获取全局锁
2、各分支事务开启,提交sql,并将结果汇报给TC
完成阶段:
各分支sql提交无异常,则将所有本地事务commit,否则rollback
XA工作模式演示
biz-admin调用user服务将用户id为1的用户名改为五,再调用order服务将订单d为1的订单金额改为50,修改成功
biz-admin调用user服务将用户id为1的用户名改为赵六,再调用order服务将订单id为1的订单金额改为60,此时发生了异常,修改不成功,结果依然是原数据
AT模式与XA模式对比
- XA模式一阶段不提交事务,锁定资源;AT模式一阶直接提交,不锁定资源
- XA模式依赖数据库机制实现回滚,AT利用数据快照(undo_log)实现数据回滚
- XA模式强一致;AT式最终一致
- 总结:
XA模式强一致性,实现容易,性能差
AT模式最终一致性,性能较好,会出现脏读,回滚异常需要人工介入
TCC模式
TCC模式工作机制
tcc 工作机制的差别在于需要自己准备三个接口,分别是锁定资源(try),确定接口(comfirm)以及取消接口
一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
二阶段 commit 行为:调用 自定义 的 commit 逻辑。
二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。
SAGA模式
Saga模式工作机制
每个操作都需要相应的一个补偿操作,一旦某个环节失败,则往回执行所有的补偿操作,实现回滚
举例说明,补偿操作可以设计为:
1、订单服务: 取消订单
2、库存服务: 恢复库存
3、支付服务: 退款。