首页 > 其他分享 >分布式事务——两阶段提交和三阶段提交

分布式事务——两阶段提交和三阶段提交

时间:2023-01-03 14:55:44浏览次数:38  
标签:事务 发起者 执行者 阶段 提交 超时 分布式

1.两阶段提交协议(2PC)

1.1 两阶段提交协议

事务发起阶段:

事务的发起者提出一个request(比如用户下单购买某个商品),要求其依赖的服务(事务的执行者)本地执行业务逻辑。执行成功本地事务不提交但要告诉发起者本地已经执行成功;执行失败执行者告诉发起者本地作业执行失败

事务提交/回滚阶段:

事务发起者根据事务发起阶段收集到的信息决定提交/回滚

如果全部执行者都反馈成功那么发起者通知所有执行者提交事务

如果存在执行者反馈失败,则发起者通知所有参与者取消事务

综上可见,无论事务发起阶段还是提交/回滚阶段,都是通过发起者向执行者发送相应指令来控制执行者作相应操作

 

流程图如下:

 

 1.2 两阶段提交——超时处理

  1. 对执行者而言:如果没有收到第二步事务,该如何处理?此时的执行者会一直锁定资源等待第二步事务。
  2. 对发起者而言:如果第一步中没有收到回复,该如果处理?此时的发起者无法得知是否所有执行者都成功锁定了资源。
  3. 对发起者而言:如果第二步中没有收到回复,该如果处理?此时的发起者无法得知是否所有执行者都成功确认了事务。

    依次回答这三个问题:

    1. 执行者没有收到第二步事务,有三种处理方案:第一种是一直锁定资源等待,第二种是超时 confirm 事务,第三种是超时 cancel 事务。对于两阶段提交而言,其他执行者在第一步是有可能返回失败的,所以显然强行 confirm 会有风险,第三种更为合理。此处有“应当 confirm 但因为网络或其他问题而没有收到,最终执行了超时 cancel”的风险,会导致数据不一致。
    2. 发起者第一步中没有收到回复,也存在两种策略:要么超时重试(再次提出事务),要么超时后当做返回失败处理。这两种可以组合使用,即多次超时重试后仍无回复则当做返回失败处理。
    3. 发起者第二步中没有收到回复,和问题 2 的处理策略类似,多次超时重试后仍无返回说明出现了异常,但不同的是这个异常是一个无法回滚的异常,意味着系统中可能出现了数据不一致,可能需要其他(很可能是人工)方式修复数据。

1.3 两阶段提交——异常重试

当执行过程中发生异常(比如宕机),事务应当可以重试。

  1. 对发起者而言:如果在第一步发生异常:部分执行者锁定了资源,而另一部分从未收到过事务请求。由于执行者会默认超时 cancel,所以发起者发起 cancel 后(或不处理,直接等待超时)重新发起新事务即可。
  2. 对发起者而言:如果在第二步发生异常:如果执行的是 cancel,则无需重试,当做成功即可(当然也可以重试)。如果执行的是 confirm,则可能发生部分机器成功 confirm,部分机器由于没有收到 confirm,默认超时 cancel 请求,从而数据不一致的风险。
  3. 对执行者而言:如果在第一步发生异常:尽量返回失败即可,超时发起者会重试/cancel 请求。不会有什么风险。
  4. 对执行者而言:如果在第二步发生异常:尽量重试并保证成功。如果执行的是 confirm,说明第一步的锁定返回了成功,所以第二步的确认只能是成功。如果是 cancel,则更应当自行重试保证资源释放。

 

2.三阶段提交协议(3PC)

CanCommit(询问阶段):

事务协调者向参与者发送事务执行请求,询问是否可以完成指令,参与者只需要回答是不是即可,不需要做正真的事务操作,这个阶段会有超时终止机制。
PreCommit(准备阶段):

事务协调者会根据参与者的反馈结果决定是否继续执行,如果在询问阶段所有参与者都返回可以执行操作,则事务协调者会向所有参与者发送PreCommit请求,参与者收到请求后会写redo和undo日志,执行事务操作但是不提交事务,然后返回ACK响应等待事务协调者的下一步通知。如果询问阶段任意参与者返回不能执行操作的结果,那么事务协调者会向所有参与者发送事务中断请求。
DoCommit(提交或回滚阶段):

这个阶段也会存在两种结果,根据上一步骤的执行结果来决定DoCommit的执行方式。如果每个参与者在PreCommit阶段都返回成功,那么事务协调者会向所有的参与者发起事务提交指令。反之,如果参与者中的任一个参与者返回失败,那么事务协调者就会发起中转指令来回滚事务。

三阶段提交是较二阶段提交在事务发起阶段前 先进行查询,确认是否可提交。

以用户下单购买某个商品”为例。对于这个场景,第 0 步会检查向优惠券服务检查优惠券是否可用、向支付业务检查账户余额是否足够、向仓储服务检查库存是否足够等。

只有当第 0 步全部返回成功时,才会执行第一步的锁定资源。这时的第一步也几乎可以全部返回成功(只有并发情况下会失败)。

因此,对于执行者而言,如果一直没有收到第二步(实际上的第三步)的事务,超时可以默认执行 confirm 操作。大多数情况下都会成功避免数据不一致。(只有并发竞争情况下有可能失败)

简而言之,三阶段提交相比两阶段提交多了第 0 步检查是否可提交。执行者的默认超时行为从 cancel 改为 confirm。

 

三阶段提交流程图

 

 

 

 

参考文献:

https://blog.csdn.net/u014635374/article/details/105948330

https://zhuanlan.zhihu.com/p/163864897

标签:事务,发起者,执行者,阶段,提交,超时,分布式
From: https://www.cnblogs.com/enhance/p/17022214.html

相关文章

  • 分布式存储(ceph)技能图谱(持续更新)
    一下为个人结合其他人对分布式存储所需的技能进行总结,绘制成如下图谱,方便针对性学习。这里对分布式存储系统接触较多的是ceph,所以在分布式存储系统分支上偏向ceph的学习......
  • jango框架:Q查询进阶操作、ORM查询优化、ORM事务操作、ORM常用字段类型、ORM常用字段
    目录Q查询进阶操作ORM查询优化ORM查询优化之only与deferORM查询优化之select_related与prefetch_relatedORM事务操作ORM常用字段类型ORM常用字段参数Ajax异步提交基础语法......
  • 如何解决分布式场景下的数据一致性问题?今天冰河的分布式锁服务插件mykit-lock开源啦
    大家好,我是冰河~~重磅消息:分布式锁插件mykit-lock正式开源开源地址:https://github.com/sunshinelyz/mykit-lock欢迎大家Star和Fork源码,并pr你牛逼哄哄的代码!框架简述mykit架......
  • form表单序列化和ajax提交表单
    页面元素<linkrel="stylesheet"href="http://lib.sinaapp.com/js/bootstrap/3.3.7/css/bootstrap.css"><scriptsrc="https://cdn.bootcdn.net/ajax/libs/layui/2.7.6/......
  • SQL注入类型及提交注入
    前言:在真实SQL注入安全测试中,我们一定要先明确提交数据及提交方法后再进行注入,其中提交数据类型和提交方法可以通过抓包分析获取,后续安全测试中也必须满足同等的操作才能......
  • 分布式存储系统 Ceph 实战操作
    目录一、概述二、cephadm工具的使用1)cephadm工具的介绍2)cephadm安装3)cephadm常用命令使用4)启用cephshell三、ceph命令使用1)添加新节点2)使用ceph安装软件3)主机操作......
  • MassTransit | 基于StateMachine实现Saga编排式分布式事务
    什么是状态机状态机作为一种程序开发范例,在实际的应用开发中有很多的应用场景,其中.NET中的async/await的核心底层实现就是基于状态机机制。状态机分为两种:有限状态机和......
  • SpringCloud分布式配置中心的搭建
    1.配置中心服务端的搭建创建模块cloud-config-center3344添加坐标<!--这是分布式的配置中心--><dependencies><!--需要引入配置中心的坐标--><dependency><......
  • 分布式 id 生成器(雪花算法)
    分布式id生成器(雪花算法)有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id。以支持业务中的高并发场景。比较典型的,电商促销时,短时间内会有大量的订......
  • 分布式测试工具的调研对比
    1.背景当自动化用例累积的越来越多,回归自动化用例的时间越来越长。我们往往会选择使用多线程的方式来跑用例集,但是用例数量达到一定数量级(千级以上)后,在单台机器上使用多线程......