分布式事务
一个微服务同时调用多个微服务,每个微服务的本地事务,也可以称为分支事务。多个有关联的分支事务一起就组成了全局事务。
每个微服务有自己独立的数据库,只能实现自身的ACID,无法实现整体的ACID
Seata
阿里巴巴的开源的分布式事务框架,保证全局事务下的所有分支事务同时成功或失败。
事务管理中的三个重要的角色:
TC
(Transaction Coordinator
) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。TM
(Transaction Manager
) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。RM
(Resource Manager
) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
其中,TM
和RM
可以理解为Seata
的客户端部分,引入到参与事务的微服务依赖中即可。将来TM
和RM
就会协助微服务,实现本地分支事务与TC
之间交互,实现事务的提交或回滚。
而TC
服务则是事务协调中心,是一个独立的微服务,需要单独部署。
部署TC服务
-
在虚拟机
root
目录下创建seata
目录,包含application.yaml
文件 -
在虚拟机的/root目录执行下面的命令:
docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \ # HTTP访问端口
-e SEATA_IP=IP \
-v ./seata:/seata-server/resources \
--privileged=true \
--network 网络名 \
-d \
seataio/seata-server -
创建
seata
数据库CREATE DATABASE IF NOT EXISTS `seata`;
USE `seata`;
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(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_status_gmt_modified` (`status` , `gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
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;
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`),
KEY `idx_xid_and_branch_id` (`xid` , `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 ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
微服务集成
例子:
-
引入依赖
<!--统一配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency> -
在
Nacos
中添加一个共享的seata
配置,命名为shared-seata.yaml
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
type: nacos # 注册中心类型 nacos
nacos:
server-addr: 192.168.150.101:8848 # nacos地址
namespace: "" # namespace,默认为空
group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
application: seata-server # seata服务名称
username: nacos
password: nacos
tx-service-group: hmall # 事务组名称
service:
vgroup-mapping: # 事务组与tc集群的映射关系
hmall: "default" -
在需要使用的微服务的
bootstrap.yaml
中添加:spring:
application:
name: trade-service # 服务名称
profiles:
active: dev
cloud:
nacos:
server-addr: 192.168.150.101 # nacos地址
config:
file-extension: yaml # 文件后缀名
shared-configs: # 共享配置
- dataId: shared-seata.yaml # 共享seata配置
……
Seata
支持四种不同的分布式事务解决方案:
XA
TCC
AT
SAGA
两阶段提交
A
是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
一阶段:
- 事务协调者通知每个事务参与者执行本地事务
- 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段:
- 事务协调者基于一阶段的报告来判断下一步操作
- 如果一阶段都成功,则通知所有事务参与者,提交事务
- 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务
XA
模式
XA
规范 是 X/Open
组织定义的分布式事务处理(DTP
,Distributed Transaction Processing
)标准,XA
规范 描述了全局的TM
与局部的RM
之间的接口,几乎所有主流的数据库都对 XA
规范 提供了支持。
RM
一阶段的工作:
- 注册分支事务到
TC
- 执行分支业务
sql
但不提交 - 报告执行状态到
TC
TC
二阶段的工作:
TC
检测各分支事务执行状态- 如果都成功,通知所有
RM
提交事务 - 如果有失败,通知所有
RM
回滚事务
RM
二阶段的工作:
- 接收
TC
指令,提交或回滚事务