前言
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:61944c4f-37bc-45f6-84c5-d7b7ba04884d
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:7511af7b-5600-460b-8c61-81bf48cc4608
在后端每个微服务都是分散和独立的,可能使用不同编程语言,使用不同的数据库,通过RPC调用完成前端用户发送的请求(任务);
假设1个用户在1个分布式微服务架构的电商网站购物,购买了1件商品点击了下单,后台需要一组微服务协作完成下单操作;
即:订单服务创建订单—>库存服务减少库存—->用户服务减少余额;
在这3个环节执行过程中,如果其中1个微服务不可用,都无法满足当前用户下单的需求;
那如何保证用户的1次操作具备数据库事务的ACID特性呢?
这就需要分布式事务;
2000年加州理工大学伯克利分校的EricBrewer教授提出在分布式架构中应当具备3个理想的指标
- Consistency(一致性)
- Availability(可用性)
- Partition tolerance (分区容错性)
称为CAP理论;
1.一致性
指分布式架构中数据的强一致性, 即使数据分布在不同节点上,1个节点写操作之后,在另1个节点的读操作,也可以读到最新状态的数据(MySQL主从之间数据同步)。
2.可用性
指服务处在100%可用的状态,用户访问分布式集群中任意1个服务 ,即使该服务故障,用户依然能得到响应,而不是超时或拒绝。
3.分区容错
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:e5ae83e7-f485-43f0-b1af-1d5346159595
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:b80fd131-1511-4a6d-a241-3eb86948ed22
二、BASE理论
在分布式微服务架构中,各个微服务之间通过网络进行RPC调用,CAP理论中的可用性和一致性就是相互矛盾的,无法同时成立;
1.CAP理论的问题
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:f7a3098e-4d4d-416a-a265-75cfb2f0d933
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:34256df5-20f1-407a-a70d-8223d3dee15c
假设G1和G2两个节点要想实现数据一致性,就需要通过网络传输同步数据,但网络传输数据是需要时间的;
忠和孝无法两全,如果G1更新了数据,在G1和G2节点通过网络传输同步数据的这1段时间里,G2节点是对外提供查询服务呢?还是不提供服务呢?
- G2提供服务就不满足一致性指标;
- G2阻塞用户请求,不提供服务就无法满足100%可用性指标;
以上是CAP理论存在的问题;
2.BASE理论
BASE理论是针对CAP理论存问题的1种解决方案,包含3个思想:
2.1.Basically Available (基本可用)
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:57048935-dcb3-4fb2-a0c9-02777403d2f7
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:f64537c8-3460-4569-8e49-3b8cfed76f6e
2.2.Soft State(软状态)
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c406c2fc-c8a7-45ee-89ed-ce4be726dcab
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:44b07c44-6eab-4705-af21-726f27ccec4a
2.3.Eventually Consistent(最终一致性)
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c60f4169-47fb-461f-a54f-35c88d22827c
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:dd678057-2f41-4469-9004-ad702bfa2611
三、分布式事务解决思路
分布式事务在设计之初借鉴CAP、BASE理论,有两种解决思路:
- AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
- CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。
但不管是哪一种模式,想要在分布式架构中控制多个事物都需要1个事务协调者(TC):
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:08f92ee3-df0f-4179-a0f9-89a3ed4b5616
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:3af1d759-87d0-4d6b-8912-84bf562bfe04
四、初识Seata
Seata是 2019 年1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:8b5040c3-71be-49d5-b259-4d82254fa58d
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:28b95e98-9c9f-4ecd-ac81-011fea1845a1
官网地址:http://seata.io/,其中的文档、播客中提供了大量的使用说明、源码分析。
1.Seata的架构
Seata事务管理中有3个重要的角色:
- TC (Transaction Coordinator) -事务协调者:搭建好的Seata服务器,所有的RM和TM都要想TC上报,当前分支事务执行的状态,以便于TC作出全局事务的回滚/提交操作(CEO);
- TM (Transaction Manager) -事务管理器:代表整个业务逻辑,决定全局事务的范围和边界,从哪个环节开始全局事务?在哪个环节提交或回滚全局事务?从哪个环节结束全局事务?(经理)
- RM (Resource Manager) -资源管理器:具体执行分支事务的微服务。(员工)
Seata基于上述架构提供了四种不同的分布式事务解决方案:
- XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
- TCC模式:最终一致的分阶段事务模式,有业务侵入
- AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
- SAGA模式:长事务模式,有业务侵入
无论采用哪1种分布式事务解决方案,都需要先搭建Seata服务器,也就是事务的协调者(TC)。
2.安装Seata
2.1.Seata配置文件
使Seata服务注册到Nacos中,并指定读取Nacos中的配置文件;
registry {
# tc服务的注册中心类,这里选择nacos,也可以是eureka、zookeeper等
type = "nacos"
nacos {
# seata tc 服务注册到 nacos的服务名称,可以自定义
application = "seata-tc-server"
serverAddr = "127.0.0.1:8848"
group = "DEFAULT_GROUP"
namespace = ""
cluster = "SH"
username = "nacos"
password = "nacos"
}
}
config {
# 读取tc服务端的配置文件的方式,这里是从nacos配置中心读取,这样如果tc是集群,可以共享配置
type = "nacos"
# 配置nacos地址等信息
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "DEFAULT_GROUP"
username = "nacos"
password = "nacos"
dataId = "seataServer.properties"
}
}
registry.conf
2.2. nacos添加配置
特别注意,为了让tc服务的集群可以共享配置,我们选择了nacos作为统一配置中心。
因此服务端配置文件 seataServer.properties文件需要在nacos中配好。
配置内容如下
registry {
# tc服务的注册中心类,这里选择nacos,也可以是eureka、zookeeper等
type = "nacos"
nacos {
# seata tc 服务注册到 nacos的服务名称,可以自定义
application = "seata-tc-server"
serverAddr = "127.0.0.1:8848"
group = "DEFAULT_GROUP"
namespace = ""
cluster = "SH"
username = "nacos"
password = "nacos"
}
}
config {
# 读取tc服务端的配置文件的方式,这里是从nacos配置中心读取,这样如果tc是集群,可以共享配置
type = "nacos"
# 配置nacos地址等信息
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "DEFAULT_GROUP"
username = "nacos"
password = "nacos"
dataId = "seataServer.properties"
}
}
seataServer.properties
2.3.创建数据库表
TC服务在管理分布式事务时,需要记录事务相关数据到数据库中,你需要提前创建好这些表。
新建一个名为seata的数据库,seata数据库中创建branch_table和global_table两张表;
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:1fc2d458-db5a-40ea-9403-1ce8f9cb8cd6
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:71bb2474-7cd0-48f9-8adf-bfa8fe08f63e
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- 分支事务表
-- ----------------------------
DROP TABLE IF EXISTS branch_table
;
CREATE TABLE branch_table
(
branch_id
bigint(20) NOT NULL,
xid
varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
transaction_id
bigint(20) NULL DEFAULT NULL,
resource_group_id
varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
resource_id
varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
branch_type
varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
status
tinyint(4) NULL DEFAULT NULL,
client_id
varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
application_data
varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
gmt_create
datetime(6) NULL DEFAULT NULL,
gmt_modified
datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (branch_id
) USING BTREE,
INDEX idx_xid
(xid
) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- 全局事务表
-- ----------------------------
DROP TABLE IF EXISTS global_table
;
CREATE TABLE global_table
(
xid
varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
transaction_id
bigint(20) NULL DEFAULT NULL,
status
tinyint(4) NOT NULL,
application_id
varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
transaction_service_group
varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
transaction_name
varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
timeout
int(11) NULL DEFAULT NULL,
begin_time
bigint(20) NULL DEFAULT NULL,
application_data
varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
gmt_create
datetime NULL DEFAULT NULL,
gmt_modified
datetime NULL DEFAULT NULL,
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;
table.sql
2.4. 启动TC服务
进入bin目录,运行其中的seata-server.bat即可
2.5.测试
打开浏览器,访问nacos地址:http://localhost:8848,然后进入服务列表页面,可以看到seata-tc-server的信息:
五、微服务集成Seata
此时Seata已经注册到Nacos并可以从Nacos中读取配置信息;
我们就可以在微服务中集成使用Seata服务了;
1.引入依赖
<dependency> <groupId>com.alibaba.cloudgroupId> <artifactId>spring-cloud-starter-alibaba-seataartifactId> <exclusions> <exclusion> <artifactId>seata-spring-boot-starterartifactId> <groupId>io.seatagroupId> exclusion> exclusions> dependency> <dependency> <groupId>io.seatagroupId> <artifactId>seata-spring-boot-starterartifactId> <version>${seata.version}version> dependency>
2.配置TC地址
微服务通过application.yml中配置的Nacos获取TC地址;
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
type: nacos # 注册中心类型 nacos
nacos:
server-addr: 127.0.0.1:8848 # nacos地址
namespace: "" # namespace,默认为空
group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
application: seata-tc-server # seata服务名称
username: nacos
password: nacos
tx-service-group: seata-demo # 事务组名称
service:
vgroup-mapping: # 事务组与cluster的映射关系
seata-demo: SH
六、Seata的事务模式
Seata提供4种事务模式,帮我们实现分布式事务;
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:cfd0a970-361d-42e1-9602-dbbb59e6fc80
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:a3dba78b-7c9f-4b5c-bcc6-a0169ba1b094
1.两阶段提交
XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
正常情况:
异常情况:
一阶段(事务预提交):
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9902c793-278b-4c22-91de-4eec139dee4f
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:60dc7c6b-a880-495a-9222-8f94f1feadb0
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:4cbcd95f-7c14-4d85-8cab-22daf4edba28
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:69946749-cdf3-48e3-acc2-0ac6cbcfc635
二阶段:
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:0c1e4ed9-0700-441d-8f78-a4e74ab454fc
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:0a9436bf-a0e9-4b56-9f3e-334555535e27
– 如果一阶段的分支事务全部预提交成功,则通知所有事务参与者去数据库正真提交事务
– 如果一阶1个事务参与者的预提交结果失败,则通知所有事务参与者回滚事务
2.XA模式
几乎所有主流的数据库都XA 规范提供了支持;
Seata的XA模式是利用数据库底层事务二阶段提交的特性,封装了二阶段提交操作方法;
2.2.Seata的XA模型
Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:
RM一阶段的工作:
① 注册分支事务到TC
② 执行分支业务sql但不提交
③ 报告执行状态到TC
TC二阶段的工作:
- TC检测各分支事务执行状态 a.如果都成功,通知所有RM提交事务 b.如果有失败,通知所有RM回滚事务
RM二阶段的工作:
- 接收TC指令,提交或回滚事务
2.3.优缺点
XA模式的优点是什么?
- 事务的强一致性,满足ACID原则。
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:d02e5fc7-adb2-46ca-849c-cce7b2105442[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:7fe846f0-117f-49f3-92d7-473ccf1e7b7e
XA模式的缺点是什么?
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c42c19df-0f67-451a-a810-03a086eae5cc
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:4310657f-6689-4832-abea-f1b80f2ab94a
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:c3f2b988-228e-4323-88d8-87393a471005
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:cc2108b9-917b-4153-a5fc-f69eb005e2fc
2.4.实现XA模式
Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:
2.4.1.修改application.yml文件
每个参与事务的微服务都需要开启XA模式:
seata:
data-source-proxy-mode: XA
2.4.2.添加注解
给发起全局事务的入口方法添加@GlobalTransactional注解
@Override
@Transactional
//给发起全局事务的入口方法添加@GlobalTransactional注解:
@GlobalTransactional
public Long create(Order order) {
// 创建订单
orderMapper.insert(order);
try {
// 扣用户余额
accountClient.deduct(order.getUserId(), order.getMoney());
// 扣库存
storageClient.deduct(order.getCommodityCode(), order.getCount());
} catch (FeignException e) {
log.error("下单失败,原因:{}", e.contentUTF8(), e);
throw new RuntimeException(e.contentUTF8(), e);
}
return order.getId();
}
2.4.3. 重启服务并测试
重启order-service,再次测试,发现无论怎样,3个微服务都能成功回滚。
3.AT模式
AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。
AT模式就是模仿了数据库底层XA二阶段提交机制,把改功能抽离出来在Seata中再实现,这样可以使Seata支持更多数据库的分布式事务操作;
阶段一RM的工作:
- 注册分支事务
- 记录undo-log(数据快照以保证事务提交失败之后可以回滚)
- 执行业务sql并提交
- 报告事务状态
阶段二提交时RM的工作:
- 删除undo-log即可
阶段二回滚时RM的工作:
- 根据undo-log恢复数据到更新前
3.1.AT与XA的区别
简述AT模式与XA模式最大的区别是什么?
- XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
- XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
- XA模式强一致;AT模式最终一致
3.2.脏写问题
在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图:
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:74378926-707a-4707-a69b-67acb09388cc
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9f721091-f337-46a2-b4f5-3cd2a2a5212f
在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。
3.3. 优缺点
AT模式的优点:
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:e6fecfa5-3f1f-44bf-96ca-a8e632f859c2
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:9fffc7c5-be30-45dd-9d40-1e8530afb237
* 利用全局锁实现读写隔离
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:56a9e4f9-54c1-4217-af2a-f8d276453043
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:adb0aed3-1161-4c56-b8c3-4b561cd8b4f7
AT模式的缺点:
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:753b7897-4107-4d74-9ac7-c69c400938a3
[En]
[TencentCloudSDKException] code:FailedOperation.ServiceIsolate message:service is stopped due to arrears, please recharge your account in Tencent Cloud requestId:60a10eae-ec39-42c3-a504-b037190a24a0
* 框架的快照功能会影响性能,但比XA模式要好很多
3.4. 实现AT模式
3.4.1.导入数据库表,记录全局锁
CREATE TABLE lock_table
(
row_key
varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
xid
varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
transaction_id
bigint(20) NULL DEFAULT NULL,
branch_id
bigint(20) NOT NULL,
resource_id
varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
table_name
varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
pk
varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
gmt_create
datetime NULL DEFAULT NULL,
gmt_modified
datetime NULL DEFAULT NULL,
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;
lock_table.sql
Original: https://www.cnblogs.com/sss4/p/16458980.html
Author: Martin8866
Title: 分布式事务(Seata)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/562573/
转载文章受原作者版权保护。转载请注明原作者出处!