文章目录

  • 什么是分布式事务
  • 分布式事务产生的原因
    • 数据库分库分表
    • 应用SOA化--微服务化
  • 分布式事务解决方案
    • 两阶段提交(2PC)
    • 两阶段提交缺点
  • 三阶段提交(3PC)
    • CanCommit阶段
    • PreCommit阶段
    • doCommit阶段
    • 总结swot(2pc,3pc)
  • 补偿事务TCC
  • 消息事务+最终一致性
    • 消息事务步骤
  • SAGA解决方案
    • 基于事件驱动实现
      • 优点:
      • 缺点:
    • 基于命令方式实现
      • 流程
      • 优点:
      • 缺点:
  • 参考文章

什么是分布式事务

  1. 指一次大的操作由不同的小操作组成的,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。从本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

分布式事务产生的原因

数据库分库分表

  1. 当数据库单表数据达到千万级别,就要考虑分库分表,那么就会从原来的一个数据库变成多个数据库。例如如果一个操作即操作了01库,又操作了02库,而且又要保证数据的一致性,那么就要用到分布式事务。

应用SOA化–微服务化

  1. 所谓的SOA化,就是业务的服务化。例如电商平台下单操作就会产生调用库存服务扣减库存和订单服务更新订单数据,那么就会设计到订单数据库和库存数据库,为了保证数据的一致性,就需要用到分布式事务。

总结:其实上面两种场景,归根到底是要操作多数据库,并且要保证数据的一致性,而产生的分布式事务的。

分布式事务解决方案

两阶段提交(2PC)

  1. XA是一个分布式事务协议,由Tuxedo提出。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、Mysql等数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交回滚。

总结:因为要操作不同的数据库,XA就是把所有操作库的提交和回滚操作交给事务管理器来操作,当一个事务出现异常,XA事务管理器就通过回滚操作,将整个未提交的事务给回滚下来。也就是说提交权交给了事务管理器

两阶段提交缺点

二阶段提交看起来确实能够提供原子性的操作,但是它存在几个缺点

  1. 同步阻塞问题

执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
问题1:同步阻塞什么意思?是指当事务没有提交时,其他事务无法执行吗?查询功能也不能执行吗?

  1. 单点故障

由于(事务管理器)协调者的重要性,一旦协调者发生故障。(本地资源管理器)参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题

  1. 数据一致

在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接收到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器无法执行事务提交。于是整个分布式系统便出现了数据不一致的现象。

  1. 二阶段无法解决的问题

参与者在发出commit消息之后宕机,而唯一接收到这条消息的协调者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交了。

三阶段提交(3PC)

  1. 三阶段提交

3PC其实在2PC的基础上增加了CanCommit阶段,是2PC的变种,并引入了超时机制。一旦事务参与者迟迟没有收到协调者的Commit请求,就会自动进行本地commit,这样相对有效的解决了协调者单点故障的问题。但是,性能和数据一致性问题没有根本解决。

  1. 3PC分为三个阶段:CanCommit、PreCommit、DoCommit

CanCommit阶段

它跟2PC的 准备阶段很像,协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。

  • 事务询问:协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应
  • 响应反馈:参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则返回No

PreCommit阶段

协调者根据参与者的响应情况来决定是否可以进行事务的PreCommit操作。根据响应情况,有以下两种可能:

  1. 假如协调者从所有的参与者获得的反馈都是Yes,那么就会执行事务的与执行。

    • 发送预提交请求:协调者向参与者发送PreCommit请求,并进入Prepared阶段。
    • 事务预提交:参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
    • 响应反馈:如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。
  2. 假如有任何一个参与者向协调者发送了No响应,或者等待超时,或者协调者都没有接到参与者的响应,那么就执行事务的中断。
    • 发送中断请求:协调者向所有参与者发送abort请求。
    • 中断事务:参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。

doCommit阶段

该阶段进行真正的事务提交,也可以分为以下两种情况:

  1. 执行提交

    • 发送提交请求:协调接收到参与者发送的ACK响应,那么将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
    • 事务提交:参与者接收到doCommit请求之后,执行正式的事务提交,并在完成事务提交之后释放所有事务资源。
    • 响应反馈:事务提交完之后,向协调者发送ACK响应。
    • 完成事务:协调者接收到所有参与者的ACK响应之后,完成事务。
  2. 中断事务
    • 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
    • 发送中断请求:协调者向所有参与者发送abort请求
    • 事务回滚:参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
    • 反馈结果:参与者完成事务回滚之后,像协调者发送ACK消息。
    • 中断事务:协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

总结swot(2pc,3pc)

相对于2PC而言,3PC对于协调者和参与者都设置了超时时间,而2PC只有协调者才拥有超时时间机制。这个优化解决了,参与者在长时间无法与协调者节点通讯的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。但是仍然没有解决数据一致性问题,即在参与者收到PreCommit请求后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。

补偿事务TCC

TCC(Try-Confirm-Cancel)又称补偿事务。它实际上与2PC、3PC一样,都是分布式事务的一种实现方案而已。它分为三个操作:

  1. Try阶段:主要是对业务系统做检测及资源预留。
  2. Confirm阶段:确认执行业务操作。
  3. Cancle阶段:取消执行业务操作。

TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在DB层面,而TCC本质上就是应用层面的2PC,需要通过业务逻辑来实现。它的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提交吞吐量。不过对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。

消息事务+最终一致性

所谓的消息事务就是基于消息中间件的两阶段提交,本质上是中间件的一种特殊利用,他是将本地事务和发消息放在一个分布式事务里,保证要么本地操作成功并且对外发消息成功,要么两者都失败,开源的RocketMQ就支持这一特性,具体原理如下:

消息事务步骤

  1. 服务A向消息中间件发送一条预备消息。
  2. 消息中间件保存预备消息并返回成功。
  3. 服务A执行本地事务。
  4. 服务A发送提交消息给消息中间件,服务B接收到消息之后执行本地事务。

基于消息中间件的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(服务A的本地操作+发消息)+服务B的本地操作,其中服务B的操作由消息驱动,只要消息事务成功,那么服务A一定成功,消息也一定发出来了,这时候服务B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到服务B操作成功,这样就变相地实现了A与B的分布式事务

  • 以上几个步骤可能存在异常情况,现在对其进行分析:

步骤一出错:则整个事务失败,不会执行服务A的本地操作。
步骤二出错:则整个事务失败,不会执行服务A的本地操作。
步骤三出错:需要做回滚预备消息,由服务A实现一个消息中间件的回调接口,消息中间件会不断执行回调接口,检查服务A事务执行是否执行成功,如果失败则回滚预备消息。
步骤四出错:这个时候服务A的本地事务是成功的,但是消息中间件不需要回滚,其实通过回调接口,消息中间件能够检查到服务A执行成功了,这个时候其实不需要服务发提交消息了,消息中间件可以自己对消息进行提交,从而完成整个消息事务。

SAGA解决方案

  1. 个人认为:SAGA的解决方案类似于消息事务,但是没有用到中间件。SAGA有两种实现方案:1、基于事件驱动方案。2、基于命令的方式
  2. SAGA的应用场景适合处理时间跨度比较长的分布式事务问题。同时对于分布式事务参与方的完成时效性没有要求

基于事件驱动实现

  1. 基于事件的方式。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应。
  2. 大致就是:每个操作都会产生一个事件,每个操作执行完后都会监听其他事件的执行情况。并根据其他服务产生的事件决定是否做出响应。

优点:

简单且容易理解。各参与方相互之间无直接沟通,完全解耦。这种方式比较适合整个分布式事务只有2-4个步骤的情形。

缺点:

这种方式如果涉及比较多的业务参与方,则比较容易失控。各业务参与方可随意监听对方的消息,以至于最后没人知道到底有哪些系统在监听哪些消息。更悲催的是,这个模式还可能产生环形监听,也就是两个业务方相互监听对方所产生的事件。

基于命令方式实现

  1. 基于命令的方式。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务。
  2. 基于命令的方式中,我们会定义一个新的服务,这个服务扮演的角色就和一支交响乐乐队的指挥一样,告诉各个业务参与方,在什么时候做什么事情。我们管这个新服务叫做协调中心。协调中心通过命令/回复的方式来和Saga中其它服务进行交互。

流程

1、订单服务创建一笔新订单,将订单状态设置为"待处理",然后让Order Saga Orchestrator(OSO)开启创建订单事务。
2、OSO发送一个"支付命令"给支付服务,支付服务完成扣款并回复"支付完成"消息。
3、OSO发送一个"备货命令"给库存服务,库存服务完成库存扣减和备货,并回复"出库"消息。
4、OSO发送一个"配送命令"给物流服务,物流服务完成配送,并回复"配送完成"消息。
5、OSO向订单服务发送"订单结束命令"给订单服务,订单服务将订单状态设置为"完成"。

  • OSO清楚一个订单处理Saga的具体流程,并在出现异常时向相关服务发送补偿命令来回滚整个分布式事务。

优点:

1、避免了业务方之间的环形依赖。
2、将分布式事务的管理交由协调中心管理,协调中心对整个逻辑非常清楚。
3、减少了业务参与方的复杂度。这些业务参与方不再需要监听不同的消息,只是需要响应命令并回复消息。
4、测试更容易(分布式事务逻辑存在于协调中心,而不是分散在各业务方)。
5、回滚也更容易。

缺点:

一个可能的缺点就是需要维护协调中心,而这个协调中心并不属于任何业务方。

参考文章

  1. 分布式事务解决方案:https://www.cnblogs.com/hujinshui/p/11482208.html
  2. 分布式事务方案SAGA:https://zhuanlan.zhihu.com/p/95852045

2021-09-16-分布式事务解决方案理解相关推荐

  1. 《深入理解分布式事务》第六章 最终一致性分布式事务解决方案

    <深入理解分布式事务>第六章 最终一致性分布式事务解决方案 文章目录 <深入理解分布式事务>第六章 最终一致性分布式事务解决方案 一.最终一致性分布式事务概述 1.典型方案 2 ...

  2. 基于真实电商的下单扣库存学习理解分布式事务解决方案

    文章目录 业务背景 分布式事务解决方案及缺点 业务过程分析 下单扣减库存的业务难点 解决方案 1. 先扣库存,后创建订单 2. 先创建订单,后扣库存 异常数据处理 1. 库存表流水表 2. 重试+回滚 ...

  3. 常用的分布式事务解决方案

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 常用的分布式事务解决方案 凌澜星空 2018-03-11 14:44:55  75315   ...

  4. 四种基于MQ的分布式事务解决方案

    在微服务的时代,分布式事务是绕不开的话题,尽管在大多数场景下,我们并不需要使用分布式事务,但是 不需要使用 不代表 可以不会使用,万一哪天真需要用到了呢?分布式事务是一个比较大的话题,今天我们来看看基 ...

  5. 分布式事务解决方案实战

    目录 1.数据库事务ACID 2.什么是分布式事务 3.单体事务和分布式事务 3.1 传统单体架构事务 3.2 微服务或者多数据源分布式事务 4.分布式事务理论基础 4.1 CAP 4.2 BASE ...

  6. 阿里开源分布式事务解决方案 Fescar 全解析

    广为人知的阿里分布式事务解决方案:GTS(Global Transaction Service),已正式推出开源版本,取名为"Fescar",希望帮助业界解决微服务架构下的分布式事 ...

  7. 微服务架构下分布式事务解决方案——阿里GTS

    1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...

  8. 微服务架构下分布式事务解决方案 —— 阿里GTS

    1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...

  9. 阿里开源分布式事务解决方案 Fescar

    微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,系统微服务化后,一个看似简单的功能,内部可能需要调用多个服务并 ...

  10. 如何选择分布式事务解决方案?

    简介: 分布式事务中涉及的参与者分布在异步网络中,参与者通过网络通信来达到分布式一致性,网络通信不可避免出现失败.超时的情况,因此分布式事务的实现比本地事务面临更多的困难.本文归纳总结五种分布式事务解 ...

最新文章

  1. 编写一个函数实现从 1 到 n 共 n 个数的累加_leetcode306_go_累加数
  2. java弹框形式输入_java中点击一个按钮弹出两个输入文本框的源代码
  3. 01_SpringCoud 整合SpringCoud alibaba Nacos
  4. java 异步得到函数返回值_使用JavaScript进行异步编程
  5. 产品经理如何应对一句话需求
  6. 提高编程技巧的十大方法
  7. 使用C#代码实现增加用户帐号
  8. Google Code Review 代码审查速度
  9. UnityShader语法英文入门
  10. 超大图片的储存/处理/显示
  11. [线性代数]向量2-范数三角不等式证明
  12. 初学makefile
  13. Ubuntu 18.04桌面版卸载不必要的自带软件
  14. el-tree 默认展开第一级节点
  15. 屏幕分辨率 VGA、HVGA、QVGA、WVGA、WQVGA
  16. 电源滤波电容如何选择
  17. 模拟自由落体运动的小球
  18. 这些朋友更适合苹果电脑,你了解吗?
  19. java计算机毕业设计智能旅游电子票务系统演示录像2020源码+mysql数据库+系统+部署+lw文档
  20. 记录IDEA导包不能导入的问题

热门文章

  1. thinkbook 如何连接手机投屏
  2. python设置笔记本屏幕背光亮度
  3. 做好网络舆情监测监控的重要性,TOOM网络舆情监控平台建设方案?
  4. AirSim无人机运动过程中图片及进行存储
  5. SQL2000服务器时间怎么修改,修改sql2000服务器ip地址
  6. 字节跳动 android 二面,今天字节跳动二面碰到个Java面试题,有大佬会吗?
  7. 硬盘mdr转换成gdp linux,外行给老爷机装linux系统始末
  8. 请打印出昨天的此时此刻
  9. Vista破解方法深度总结(目前共7种方法) ayconanw撰写
  10. CSDN居然免费送会员?快来参与!