Seata 解决分布式事务理论与实践(2)

简介: Seata 解决分布式事务理论与实践(2)

4.动手实践

下面我们就一起学习下Seata中的四种不同的事务模式。


4.1.XA模式

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。


4.1.1.两阶段提交

XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。


正常情况:


微信截图_20231016204625.png

异常情况:

微信截图_20231016204633.png

一阶段:


事务协调者通知每个事物参与者执行本地事务

本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁

二阶段:


事务协调者基于一阶段的报告来判断下一步操作

如果一阶段都成功,则通知所有事务参与者,提交事务

如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务


4.1.2.Seata的XA模型

Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:

微信截图_20231016204750.png

RM一阶段的工作:


① 注册分支事务到TC


② 执行分支业务sql但不提交


③ 报告执行状态到TC


TC二阶段的工作:


TC检测各分支事务执行状态


a.如果都成功,通知所有RM提交事务


b.如果有失败,通知所有RM回滚事务


RM二阶段的工作:


接收TC指令,提交或回滚事务


4.1.3.优缺点

XA模式的优点是什么?


事务的强一致性,满足ACID原则。

常用数据库都支持,实现简单,并且没有代码侵入

XA模式的缺点是什么?


因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差

依赖关系型数据库实现事务

4.1.4.实现XA模式

Seata 的 starter 已经完成了 XA 模式的自动装配,实现非常简单,步骤如下:


1)修改application.yml文件(每个参与事务的微服务),开启XA模式:

seata:
  data-source-proxy-mode: XA

微信截图_20231016204830.png

2)给发起全局事务的入口方法添加@GlobalTransactional注解:

本例中是OrderServiceImpl中的create方法.

@Override
@GlobalTranaction
public Long create(Order order){
    // TODO
}

3)重启服务并测试


重启order-service,再次测试,发现无论怎样,三个微服务都能成功回滚。


4.2.AT模式

AT模式同样是分阶段提交的事务模型,不过却弥补了XA模型中资源锁定周期过长的缺陷。(效率比XA高 但是一致性比XA若)


4.2.1.Seata的AT模型

基本流程图:

微信截图_20231016204908.png

阶段一RM的工作:


注册分支事务

记录undo-log(数据快照)

执行业务sql并提交

报告事务状态

阶段二提交时RM的工作:


删除undo-log即可

阶段二回滚时RM的工作:


根据undo-log恢复数据到更新前


4.2.2.流程梳理

我们用一个真实的业务来梳理下AT模式的原理。


比如,现在又一个数据库表,记录用户余额:

微信截图_20231016204919.png

其中一个分支业务要执行的SQL为:

update tb_account set money = money - 10 where id = 1

AT模式下,当前分支事务执行流程如下:

一阶段:

1)TM发起并注册全局事务到TC

2)TM调用分支事务

3)分支事务准备执行业务SQL

4)RM拦截业务SQL,根据where条件查询原始数据,形成快照。

{
    "id": 1, "money": 100
}

5)RM执行业务SQL,提交本地事务,释放数据库锁。此时 money = 90


6)RM报告本地事务状态给TC


二阶段:


1)TM通知TC事务结束


2)TC检查分支事务状态


a)如果都成功,则立即删除快照


b)如果有分支事务失败,需要回滚。读取快照数据({"id": 1, "money": 100}),将快照恢复到数据库。此时数据库再次恢复为100


流程图:

微信截图_20231016205024.png

微信截图_20231016205041.png

4.2.3.AT与XA的区别

简述AT模式与XA模式最大的区别是什么?


XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。

XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。

XA模式强一致;AT模式最终一致

4.2.4.脏写问题

在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图:


微信截图_20231016205051.png

解决思路 就是引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。

微信截图_20231016205129.png

4.2.5.优缺点

AT模式的优点:


一阶段完成直接提交事务,释放数据库资源,性能比较好

利用全局锁实现读写隔离

没有代码侵入,框架自动完成回滚和提交

AT模式的缺点:


两阶段之间属于软状态,属于最终一致

框架的快照功能会影响性能,但比XA模式要好很多

4.2.6.实现AT模式

AT模式中的快照生成、回滚等动作都是由框架自动完成,没有任何代码侵入,因此实现非常简单。


只不过,AT模式需要一个表来记录全局锁、另一张表来记录数据快照undo_log。


1)导入数据库表,记录全局锁


导入如下的Sql语句,其中lock_table导入到TC服务关联的数据库,undo_log表导入到微服务关联的数据库:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',
  `rollback_info` longblob NOT NULL COMMENT 'rollback info',
  `log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
  `log_created` datetime(6) NOT NULL COMMENT 'create datetime',
  `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of undo_log
-- ----------------------------
-- ----------------------------
-- 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,
  `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;
SET FOREIGN_KEY_CHECKS = 1;

2)修改application.yml文件,将事务模式修改为AT模式即可:

seata:
  data-source-proxy-mode: AT # 默认就是AT

3)重启服务并测试


5.高可用

Seata 的 TC 服务作为分布式事务核心,一定要保证集群的高可用性。


5.1.高可用架构模型

搭建TC服务集群非常简单,启动多个TC服务,注册到nacos即可。


但集群并不能确保100%安全,万一集群所在机房故障怎么办?所以如果要求较高,一般都会做异地多机房容灾。


比如一个TC集群在上海,另一个TC集群在杭州:

微信截图_20231016205231.png

微服务基于事务组(tx-service-group)与TC集群的映射关系,来查找当前应该使用哪个TC集群。当SH集群故障时,只需要将vgroup-mapping中的映射关系改成HZ。则所有微服务就会切换到HZ的TC集群了。

5.2.实现高可用

总结

分布式事务:
  在分布式架构中一个业务需要跨对个微服务,需要这多个微服务执行的状态保持一致.
分布式事务理论基础:
  CAP定理:
    C: 一致性
          在微服务架构中,从任何节点读取到的数据应当是一致的.
        A: 可用性
          在服务不宕机的情况下,必须返回预期的结果
        P: 分区容错
          在微服务架构中是避免不了的.
  BASE理论:
    - Basically Available 基本可用
    - Soft State 软状态
    - Eventually Consistent 最终一致性
  方案:
  AP: 可用性
      软状态: 允许不同的分支事务短时间内状态不一致
      但软状态过后需要保证最终一致.
      各个分支执行自己的操作,执行完毕后,直接提交事务即可.
      如果有分支出现失败的请求,事务协调者会通过各个分支,进行补救
  CP: 强一致性
      在所有的分支事务执行完毕后,等待协调事务发送最终提交或回滚事务的通知
===========================Seata======================
seata-TC: 事务协调者
  连接mysql数据库: 将事务的各种状态信息保存到mysql数据库表中
  记录全局事务
  记录全局事务包含的分支事务
seata-TM: 事务管理器
  开启全局事务
  提交/回滚全局事务
seata-RM: 资源管理器
  分支事务管理
----------------------------------
Seata-分布式事务模式:
  XA模式: CP思想(强一致性)
  AT模式: AP思想(最终一致)
    软状态: 每个分支事务都可以独立提交
    TM--->TC: 开启全局事务
    TM--->分支
      获取全局事务锁
      undo_log快照:
    before-image: 在分支事务对数据库中的数据操作前进行前置快照
        after-image: 在分支事务对数据库中的数据操作后进行后置快照
      如果各个分支都执行成功了---> 删除快照
      如果执行失败--->恢复快照(执行事务的补偿过程)
      释放全局事务锁
    注意事项: 主要使用在关系型数据库中
  TCC模式: AP思想
    try:
      判断cancel是否执行,如果未执行,正常执行即可
        校验,冻结
      如果执行过:
        不再执行任何逻辑,删除冻结数据
    confirm: 执行成功
      删除冻结数据
    cancel: 执行失败
      执行补偿过程
      判断try是否执行了,如果执行了
          恢复冻结数据
          删除冻结数据
      如果try没有执行:
          空回滚: 添加一条冻结数据,并设置状态
  SAGA模式: AP思想

0.回顾

在分布式(微服务)系统中,往往一个业务需要调用多个微服务,且还需要保证当前业务的完整性.
一个业务(事务):
  组成这个业务的各个单元,要么都成功,要么都失败.
指导思想:
  CAP定理:
  BASE理论:
Alibaba:在CAP定理和BASE理论的基础上进行实践后的产物.
  Seata: 
Seata实现方式:
  Seata角色:
    TC: 事务协调者
            安装Seata(服务)软件
        TM: 事务管理器
        RM: 资源管理器(分支事务管理器)
        注意: 当我们在微服务项目中导入Seata的依赖后,就相当于拥有了TM和RM两个角色
    Seata模式:
    XA模式: CP思想,强一致性
        AT模式: AP思想,最终一致
        TCC模式: AP思想,最终一致
        SAGA模式: Ap思想,最终一致
    Seata模式原理
    Seata模式实现方式

管理器

开启全局事务

提交/回滚全局事务

seata-RM: 资源管理器

分支事务管理

Seata-分布式事务模式:

XA模式: CP思想(强一致性)

AT模式: AP思想(最终一致)

软状态: 每个分支事务都可以独立提交

TM—>TC: 开启全局事务

TM—>分支

获取全局事务锁

undo_log快照:

before-image: 在分支事务对数据库中的数据操作前进行前置快照

after-image: 在分支事务对数据库中的数据操作后进行后置快照

如果各个分支都执行成功了—> 删除快照

如果执行失败—>恢复快照(执行事务的补偿过程)

释放全局事务锁

注意事项: 主要使用在关系型数据库中

TCC模式: AP思想

try:

判断cancel是否执行,如果未执行,正常执行即可

校验,冻结

如果执行过:

不再执行任何逻辑,删除冻结数据

confirm: 执行成功

删除冻结数据

cancel: 执行失败

执行补偿过程

判断try是否执行了,如果执行了

恢复冻结数据

删除冻结数据

如果try没有执行:

空回滚: 添加一条冻结数据,并设置状态

SAGA模式: AP思想

## 0.当前存在的问题?
```java
在分布式(微服务)系统中,往往一个业务需要调用多个微服务,且还需要保证当前业务的完整性.
一个业务(事务):
  组成这个业务的各个单元,要么都成功,要么都失败.
指导思想:
  CAP定理:
  BASE理论:
Alibaba:在CAP定理和BASE理论的基础上进行实践后的产物.
  Seata: 
Seata实现方式:
  Seata角色:
    TC: 事务协调者
            安装Seata(服务)软件
        TM: 事务管理器
        RM: 资源管理器(分支事务管理器)
        注意: 当我们在微服务项目中导入Seata的依赖后,就相当于拥有了TM和RM两个角色
    Seata模式:
    XA模式: CP思想,强一致性
        AT模式: AP思想,最终一致
        TCC模式: AP思想,最终一致
        SAGA模式: Ap思想,最终一致
    Seata模式原理
    Seata模式实现方式
相关文章
|
25天前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
9天前
|
运维 Kubernetes 调度
阿里云容器服务 ACK One 分布式云容器企业落地实践
阿里云容器服务ACK提供强大的产品能力,支持弹性、调度、可观测、成本治理和安全合规。针对拥有IDC或三方资源的企业,ACK One分布式云容器平台能够有效解决资源管理、多云多集群管理及边缘计算等挑战,实现云上云下统一管理,提升业务效率与稳定性。
|
12天前
|
消息中间件 SQL 中间件
大厂都在用的分布式事务方案,Seata+RocketMQ带你打破10万QPS瓶颈
分布式事务涉及跨多个数据库或服务的操作,确保数据一致性。本地事务通过数据库直接支持ACID特性,而分布式事务则需解决跨服务协调难、高并发压力及性能与一致性权衡等问题。常见的解决方案包括两阶段提交(2PC)、Seata提供的AT和TCC模式、以及基于消息队列的最终一致性方案。这些方法各有优劣,适用于不同业务场景,选择合适的方案需综合考虑业务需求、系统规模和技术团队能力。
98 7
|
16天前
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
48 4
|
20天前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
38 8
|
24天前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
44 6
|
24天前
|
数据库
如何在Seata框架中配置分布式事务的隔离级别?
总的来说,配置分布式事务的隔离级别是实现分布式事务管理的重要环节之一,需要认真对待和仔细调整,以满足业务的需求和性能要求。你还可以进一步深入研究和实践 Seata 框架的配置和使用,以更好地应对各种分布式事务场景的挑战。
28 6
|
22天前
|
消息中间件 运维 数据库
Seata框架和其他分布式事务框架有什么区别
Seata框架和其他分布式事务框架有什么区别
23 1
|
3月前
|
运维 Kubernetes 调度
阿里云容器服务 ACK One 分布式云容器企业落地实践
3年前的云栖大会,我们发布分布式云容器平台ACK One,随着3年的发展,很高兴看到ACK One在混合云,分布式云领域帮助到越来越多的客户,今天给大家汇报下ACK One 3年来的发展演进,以及如何帮助客户解决分布式领域多云多集群管理的挑战。
阿里云容器服务 ACK One 分布式云容器企业落地实践
|
3月前
|
SQL NoSQL 数据库
SpringCloud基础6——分布式事务,Seata
分布式事务、ACID原则、CAP定理、Seata、Seata的四种分布式方案:XA、AT、TCC、SAGA模式
SpringCloud基础6——分布式事务,Seata