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月前
|
NoSQL 关系型数据库 MySQL
分布式锁:不同实现方式实践测评
分布式锁:不同实现方式实践测评
29 0
|
1月前
|
SQL 关系型数据库 数据库
学习分布式事务Seata看这一篇就够了,建议收藏
学习分布式事务Seata看这一篇就够了,建议收藏
|
2月前
|
关系型数据库 MySQL 数据库
分布式事务Seata
分布式事务Seata
|
2月前
|
Java 数据库连接 API
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
60 0
|
2月前
|
存储 Oracle 关系型数据库
分布式事物【Seata实现、下载启动Seata服务、搭建聚合父工程构建】(四)-全面详解(学习总结---从入门到深化)
分布式事物【Seata实现、下载启动Seata服务、搭建聚合父工程构建】(四)-全面详解(学习总结---从入门到深化)
45 0
|
开发框架 Java 数据库连接
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)(下)
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
37 0
|
1天前
|
SQL 存储 运维
分布式事务Seata实践(上)
分布式事务Seata实践
5 0
|
27天前
|
SQL 数据库 Windows
SpringCloud集成seata分布式事务控制
SpringCloud集成seata分布式事务控制
16 0
|
29天前
|
存储 Java 应用服务中间件
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
52 0
|
1月前
|
SQL SpringCloudAlibaba 中间件
SpringCloud Alibaba Seata处理分布式事务--学习笔记
SpringCloud Alibaba Seata处理分布式事务--学习笔记
26 0

热门文章

最新文章