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模式实现方式
相关文章
|
2天前
|
负载均衡 监控 Dubbo
Java微服务架构设计与实践:构建可伸缩的分布式系统
【4月更文挑战第2天】微服务架构响应现代业务需求,通过拆分大型应用为独立服务实现模块化和可扩展性。Java中的Spring Boot和Dubbo等框架支持服务注册、负载均衡等功能。遵循单一职责、自治性和面向接口原则,每个服务专注特定逻辑,独立部署运行。实际项目中,如电商系统,服务按功能拆分,提升可维护性和扩展性。还需考虑服务通信、数据一致性和监控等复杂话题。Java微服务架构助力构建高效、灵活的应用,应对未来挑战。
Java微服务架构设计与实践:构建可伸缩的分布式系统
|
2天前
|
存储 关系型数据库 MySQL
基于Seata实现分布式事务
通过以上步骤,你可以使用 Seata 实现分布式事务,确保在微服务架构中的事务一致性。Seata 支持多种语言和框架,能够满足不同业务场景的需求。欢迎关注威哥爱编程,一起学习成长。
|
2天前
|
存储 Java 分布式数据库
【分布式计算框架】HBase数据库编程实践
【分布式计算框架】HBase数据库编程实践
12 1
|
2天前
|
分布式计算 并行计算 Java
【分布式计算框架】 MapReduce编程初级实践
【分布式计算框架】 MapReduce编程初级实践
9 2
|
2天前
|
分布式计算 数据可视化 Hadoop
【分布式计算框架】HDFS常用操作及编程实践
【分布式计算框架】HDFS常用操作及编程实践
6 1
|
2天前
|
存储 大数据 Apache
深入理解ZooKeeper:分布式协调服务的核心与实践
【5月更文挑战第7天】ZooKeeper是Apache的分布式协调服务,确保大规模分布式系统中的数据一致性与高可用性。其特点包括强一致性、高可用性、可靠性、顺序性和实时性。使用ZooKeeper涉及安装配置、启动服务、客户端连接及执行操作。实际应用中,面临性能瓶颈、不可伸缩性和单点故障等问题,可通过水平扩展、集成其他服务和多集群备份来解决。理解ZooKeeper原理和实践,有助于构建高效分布式系统。
|
2天前
|
Windows
Windows系统下安装分布式事务组件Seata
Windows系统下安装分布式事务组件Seata
|
2天前
|
SQL 容灾 数据库
分布式事务Seata
在分布式架构系统中,服务不止一个,一个完整的业务链路肯定也不止调用一个服务,此时每个服务都有自己的数据库增删改查,而每一个写操作对应一个本地事务。如果想要确保全部的业务状态一致,也就意味着需要所有的本地事务状态一致,这在我们之前的学习中肯定是不具备的,如何做到跨服务、跨数据源的事务一致性将是本章节的重点学习内容。
30 2
|
2天前
|
缓存 分布式计算 负载均衡
Java分布式系统设计与实践
Java分布式系统设计与实践
17 0
|
2天前
|
分布式计算 并行计算 数据处理
NumPy的并行与分布式计算实践
【4月更文挑战第17天】本文探讨了如何使用NumPy进行并行和分布式计算以提升效率。介绍了利用`numexpr`加速多核CPU计算,设置`NUMPY_NUM_THREADS`环境变量实现多线程,并通过Dask和PySpark进行分布式计算。Dask允许无缝集成NumPy,而PySpark则将NumPy数组转换为RDD进行并行处理。这些方法对处理大规模数据至关重要。