单个掉队,导致集体被动摆烂;

一、业务背景

在分布式架构中,事务管理是个无法避开的复杂问题,虽然有多种解决方案,但是需要根据业务去选择合适的;

从个人最近几年的实践经验来看,Seata组件的AT模式比较常用,本文从实际的案例出发,来深入分析该模式的原理;

首先创建一个全局事务管理的接口,这里是在Facade服务中开启全局事务;

请求经过三个微服务,并且各个服务都进行数据源的操作,然后模拟链路成功和异常的情况,来分析不同状态的逻辑实现;

二、Seata架构

1、核心组件

三大组件

  • TC:事务协调者

即Transaction Coordinator,维护全局和分支事务的状态,驱动全局事务提交或回滚。

  • TM:事务管理器

即Transaction Manager,定义全局事务的范围,开始事务、提交事务,回滚事务。

  • RM:资源管理器

即Resource Manager,管理分支事务处理的资源,向TC注册分支事务,报告分支事务的状态,驱动分支事务提交或回滚。

基础交互

TC是需要独立部署的服务,TM和RM是集成在服务中,三大组件相互协作,共同完成分布事务的管理;

2、AT模式

事务模型

AT是Seata默认的模式,需要基于支持本地ACID事务的关系型数据库;Java应用,通过JDBC访问数据库;基于案例流程,先分析AT的事务模型;

2.1 TM负责定义全局事务的边界,向TC申请,开启一个全局事务;

2.2 全局事务创建成功后,生成全局唯一的XID;

2.3 XID会在微服务请求链路上下文中传播;

2.4 RM向TC注册分支事务,并归属到XID对应的全局事务进行调度;

2.5 TM向TC发起相应XID的全局事务提交或回滚决议;

2.6 TC完成对XID管理的全部分支事务提交或回滚的调度;

核心机制

执行阶段:每个微服务的请求完成后,基于本地数据库的事务能力,保证业务数据和回滚日志在同一个本地事务中提交,快速释放连接和对资源的锁定;

完成阶段:全局提交时分支事务已经完成提交,会清理回滚日志,快速结束流程;全局回滚基于XID和BranchID查询回滚日志,完成数据回滚;

数据源代理

在AT模式中,应用需要使用Seata组件中的JDBC代理数据源DataSourceProxy,实现对真正目标数据源的代理访问;

三、案例分析

1、流程分析

案例的简单描述

在案例中涉及三个服务,Facade服务开启全局事务,然后分别请求Account和Quartz服务的更新接口,通过Quartz接口是否抛异常来调试AT模式的原理;

从实际的请求执行来说,绝大多数的请求都是可以执行成功的,而AT模式的异步化提交极大限度的顾及全局事务的效率问题,少数失败的情况也可以通过回滚日志进行反向补偿;

2、写隔离

上述流程分析AT模式的原子性,即多个分支事务要么都成功要么都失败,接下来分析多个事务中的全局锁隔离机制,先看写隔离,假设TX1先开始;

TX1逻辑

  • TX1开始本地事务,拿到本地锁,然后执行更新操作;
  • TX1本地事务提交前,需要先获取全局锁,否则无法提交;
  • TX1获取全局锁并提交,释放本地锁,但未释放全局锁;

TX2逻辑

  • TX2此时开始本地事务,拿到本地锁;
  • TX2执行本地事务提交前,尝试获取全局锁;
  • 由于全局锁被TX1持有,TX2会重试等待全局锁;

假设TX1全局提交

  • TX1如果全局事务提交,会释放全局锁;
  • TX2获取全局锁成功,执行本地事务提交;

假设TX1全局回滚

  • TX1如果全局事务回滚,要重新获取数据的本地锁,进行回滚的补偿动作;
  • TX2如果仍在等待全局锁,并且还持有本地锁,TX1事务回滚失败,会不断的重试;
  • 当TX2等待全局锁超时,会放弃全局锁并回滚本地事务,释放本地锁;
  • TX1最终获取数据的本地锁,完成回滚动作;

在该过程中,TX1在结束前一直持有全局锁,TX2获取不到全局锁无法对相同的数据执行更新动作,所以避免了脏写的问题;

3、读隔离

在数据库本地隔离级别为读已提交或以上的基础上,Seata的AT模式默认全局隔离级别是读未提交;如果需要全局的读已提交,可以通过SELECT FOR UPDATE语句的代理;

该语句的执行也需要获取全局锁,如果全局锁被TX1持有,TX2会释放本地锁,查询会被阻塞并进行重试,拿到全局锁读取成功后返回;

四、对比XA模式

XA是一个分布式事务分段提交协议;事务管理器即TM:作为全局事务的调度者,负责整个事务中本地资源的提交和回滚;本地资源管理器即RM:大部分关系型数据库都实现了XA接口;

TM先向所有的参与事务的RM发送确认请求,根据确认的结果,判断是调用RM的commit提交还是rollback回滚;

XA具有强一致性,在2段提交的过程中,会持有资源的锁,如果是在交易下单等复杂链路中,并且并发量很高,会存在长事务风险,XA无法满足该类高并发的场景;

而在Seata的AT模式中,在服务执行完成后,直接进行RM提交和资源释放,提供了对CAP理论相对平衡的解决方案,并且没有侵入业务工程;

五、参考源码

应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent 组件封装:
https://gitee.com/cicadasmile/butte-frame-parent

深入浅出Seata的AT模式的更多相关文章

  1. 分布式事务与Seate框架(3)——Seata的AT模式实现原理

    前言 在上两篇博文(分布式事务与Seate框架(1)--分布式事务理论.分布式事务与Seate框架(2)--Seata实践)中已经介绍并实践过Seata AT模式,这里一些例子与概念来自这两篇(特别是 ...

  2. 阿里神器 Seata 实现 TCC模式 解决分布式事务,真香!

    今天这篇文章介绍一下Seata如何实现TCC事务模式,文章目录如下: 什么是TCC模式? TCC(Try Confirm Cancel)方案是一种应用层面侵入业务的两阶段提交.是目前最火的一种柔性事务 ...

  3. 深入浅出AQS之共享锁模式

    在了解了AQS独占锁模式以后,接下来再来看看共享锁的实现原理. 原文地址:http://www.jianshu.com/p/1161d33fc1d0 搞清楚AQS独占锁的实现原理之后,再看共享锁的实现 ...

  4. 深入浅出设计模式——简单工厂模式(Simple Factory)

    介绍简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些.因为它至少不是Gof23种设计模式之一.但它在实际的编程中经常被用到,而且思想也非常简单,可以说是工厂方法模式的一个引导,所以我想 ...

  5. 深入浅出设计模式——工厂方法模式(Factory Method)

    介绍在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计模式的创建型设计模式.它解决的仍然是软件设计中与创建对象有关的问题.它可以更好的处理客户的需求变化. 引入我 ...

  6. 深入浅出设计模式——抽象工厂模式(Abstract Factory)

    模式动机在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法.但是有时候我们需要一个工厂可 ...

  7. 深入浅出设计模式——享元模式(Flyweight Pattern)

    模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生 ...

  8. 深入浅出设计模式——职责链模式(Chain of Responsibility Pattern)

    模式动机 职责链可以是一条直线.一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求.链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传 ...

  9. 深入浅出设计模式——中介者模式(Mediator Pattern)

    模式动机 在用户与用户直接聊天的设计方案中,用户对象之间存在很强的关联性,将导致系统出现如下问题: 系统结构复杂:对象之间存在大量的相互关联和调用,若有一个对象发生变化,则需要跟踪和该对象关联的其他 ...

  10. linux(centos8):安装分布式事务服务seata(file单机模式,seata 1.3.0/centos 8.2)

    一,什么是seata? Seata:Simpe Extensible Autonomous Transcaction Architecture, 是阿里中间件,开源的分布式事务解决方案. 前身是阿里的 ...

随机推荐

  1. 对循环神经网络参数的理解|LSTM RNN Input_size Batch Sequence

    在很多博客和知乎中我看到了许多对于pytorch框架中RNN接口的一些解析,但都较为浅显甚至出现一些不准确的理解,在这里我想阐述下我对于pytorch中RNN接口的参数的理解. 我们经常看到的RNN网 ...

  2. ubuntu20.04详细安装教程

    1.运行虚拟机,加载一段时间后弹出"安装"界面.语言栏倒数第三个是中文.点击[安装 Ubuntu]. 2.键盘布局,[继续] 3.更新和其他软件,取消[安装Ubuntu时下载更新] ...

  3. 基于QT和C++实现的翻金币游戏

    基于QT和C++的翻金币游戏 声明: QT翻金币项目可以说是每个新学QT的同学都会去写的一个项目,网上的源码也很多,我也是最近刚开始学QT,所以也参考了很多前辈的代码自己重新敲了一遍代码. 游戏介绍: ...

  4. Dubbo 03: 直连式 + 接口工程

    进一步改正dubbo框架中简单的直连式的不足 需要用到3个相互独立的maven工程,项目1为maven的java工程作为接口工程,项目2,3为maven的web工程 工程1:o3-link-inter ...

  5. 齐博X1-栏目的调用2

    fun('sort@fathers',$fid,'cms')  获取上层多级栏目这样的,比如我们现在所属第三级栏目,现在可以利用这个函数获取第二级和第一级的栏目,当然自身也会被调用出来,所以此函数用的 ...

  6. .net core -利用 BsonDocumentProjectionDefinition 和Lookup 进行 join 关联 MongoDB 查询

    前序 前段时间由于项目需要用到MongoDB,但是MongoDB不建议Collection join  查询,网上很多例子查询都是基于linq 进行关联查询.但是在stackoverflow找到一个例 ...

  7. C语言整人关机程序

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char input ...

  8. 4.pygame快速入门-事件监听

    事件event:游戏启动后,用户针对游戏的所有操作 监听:在游戏循环中,判断用户的具体操作 pygame中通过pygame.event.get()可以获得当前用户所做动作的事件列表   事件监听 wh ...

  9. 闻道Go语言,6月龄必知必会

    大家好,我是马甲哥, 学习新知识, 我的策略是模仿-->归纳--->举一反三, 在同程倒腾Go语言一年有余,本次记录<闻道Go语言,6月龄必知必会>,形式是同我的主力语言C#做 ...

  10. 第二阶段:高级核心基础知识·第4章shell特性·2

    1.统计日志,日志内容 39.96.187.239 - - [11/Nov/2019:10:08:01 +0800] "GET / HTTP/1.1" 302 0 "-& ...