当前位置: 首页 > news >正文

分布式事务:二阶段提交和三阶段提交底层原理

二阶段提交

两阶段提交协议的目标在于为分布式系统保证数据的一致性,顾名思义,该协议将一个分布式的事务过程拆分成两个阶段: 投票事务 提交 ,为了让整个数据库集群能够正常的运行,该协议指定了一个 协调者 单点,用于协调整个数据库集群各节点的运行

第一阶段:投票

  1. 协调者向所有的参与者发送事务执行请求,并等待参与者反馈事务执行结果;
  2. 事务参与者收到请求之后,执行事务但不提交,并记录事务日志;
  3. 参与者将自己事务执行情况反馈给协调者,同时阻塞等待协调者的后续指令
协调者->参与者集群: 发送执行事务请求
Note over 参与者集群: 所有参与者执行事务,但不提交
参与者集群-->协调者: 反馈执行结果

第二阶段:事务提交

  1. 协调者向各个参与者发送 commit 通知,请求提交事务;
  2. 参与者收到事务提交通知之后执行 commit 操作,然后释放占有的资源;
  3. 参与者向协调者返回事务 commit 结果信息。
执行成功的情况
Note over 参与者集群,协调者:第一阶段
协调者->参与者集群: 发送执行事务请求
Note over 参与者集群: 所有参与者集群执行事务,但不提交
Note over 参与者集群: 记录日志
Note over 参与者集群,协调者:第二阶段
参与者集群->协调者: 所有事务执行成功
协调者->参与者集群: 发送提交(commit)请求
Note over 参与者集群: 执行提交操作(commit)
执行失败的情况
Note over 参与者集群,协调者:第一阶段
协调者->参与者集群: 发送执行事务请求
Note over 参与者集群: 参与者集群执行事务,但不提交
Note over 参与者集群: 记录日志
Note over 参与者集群,协调者:第二阶段
参与者集群->协调者: 其中一个参与者执行失败
协调者->参与者集群: 发送回滚(rollback)请求
Note over 参与者集群: 执行回滚操作(rollback)

so,二阶段提交的整体流程图是这样的

二阶段提交出现的问题

两阶段提交协议原理简单、易于实现,但是缺点也是显而易见的,主要以下2个问题

1. 单点故障问题

协调者在整个两阶段提交过程中扮演着非常重要的角色,一旦协调者所在服务器宕机,就会影响整个数据库集群的正常运行。比如在第二阶段中,如果协调者因为故障不能正常发送事务提交或回滚通知,那么参与者们将一直处于阻塞状态,整个数据库集群将无法提供服务。

2. 同步阻塞

两阶段提交执行过程中,所有的参与者都需要听从协调者的统一调度,期间若协调者处于阻塞状态而不能从事其他操作,这样效率极其低下。

3. 数据不一致性

两阶段提交协议虽然是解决了分布式一致性,但仍然存在数据不一致性的可能性。比如在第二阶段中,假设协调者发出了事务 commit 通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit 操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。

针对上述问题可以引入 超时机制 和 互询机制 在很大程度上予以解决。

三阶段提交

针对两阶段提交存在的问题,三阶段提交协议通过引入一个 准备 阶段,以及 超时策略 来减少集群的阻塞时间,提升系统性能;三个杰顿分别为:

  • 第一阶段:准备
  • 第二阶段:预提交
  • 第三阶段:事务提交

第一阶段:准备

该阶段协调者会去询问各个参与者是否能够正常执行事务,参与者根据自身情况回复,具体步骤如下:

  1. 协调者向各个参与者发送事务询问通知,询问是否可以执行事务操作,并等待回复;
  2. 各个参与者依据自身状况回复一个预估值,如果预估自己能够正常执行事务就返回确定信息,并进入预备状态,否则返回否定信息

第二阶段:预提交

在预提交阶段下,协调者会根据第一阶段的询盘结果采取相应操作,询盘结果主要有 3 种:

  1. 所有的参与者都返回确定信息。
  2. 一个或多个参与者返回否定信息。
  3. 协调者等待超时

针对第 1 种情况,协调者会向所有参与者发送事务执行请求,具体步骤如下:

  1. 协调者向所有的事务参与者发送事务执行通知;
  2. 参与者收到通知后执行事务但不提交;
  3. 参与者将事务执行情况返回给客户端。

在上述步骤中,如果参与者等待超时,则会中断事务
针对第 2 和第 3 种情况,协调者认为事务无法正常执行,于是向各个参与者发出 abort 通知,请求退出预备状态,具体步骤如下:

  1. 协调者向所有事务参与者发送 abort 通知;
  2. 参与者收到通知后中断事务。

第三阶段:事务提交

如果第二阶段事务未中断,那么本阶段协调者将会依据事务执行返回的结果来决定提交或回滚事务,分为 3 种情况:

  1. 所有的参与者都能正常执行事务。
  2. 一个或多个参与者执行事务失败。
  3. 协调者等待超时。

针对第 1 种情况,协调者向各个参与者发起事务提交请求,具体步骤如下:

  1. 协调者向所有参与者发送事务 commit 通知;
  2. 所有参与者在收到通知之后执行 commit 操作,并释放占有的资源;
  3. 参与者向协调者反馈事务提交结果。

针对第 2 和第 3 种情况,协调者认为事务无法成功执行,于是向各个参与者发送事务回滚请求,具体步骤如下:

  1. 协调者向所有参与者发送事务 rollback 通知;
  2. 所有参与者在收到通知之后执行 rollback 操作,并释放占有的资源;
  3. 参与者向协调者反馈事务回滚结果。
超时策略

在第三阶段如果因为协调者或网络问题,导致参与者迟迟不能收到来自协调者的 commit 或 rollback 请求,那么参与者将不会如两阶段提交中那样陷入阻塞,而是等待超时后继续 commit,相对于两阶段提交虽然降低了同步阻塞,但仍然无法完全避免数据的不一致。

三阶段提交整体流程图如下

结语

两阶段提交协议中所存在的长时间阻塞状态发生的几率还是非常低的,所以虽然三阶段提交协议相对于两阶段提交协议对于数据强一致性更有保障,但是因为效率问题,两阶段提交协议在实际系统中反而更加受宠。

http://www.dtcms.com/a/301447.html

相关文章:

  • AI时代,我们更需要自己的开发方式与平台
  • java--函数式接口全面总结与使用场景指南
  • LeetCode 611.有效三角形的个数
  • python---eval函数
  • Ashampoo Background Remover(照片去背景工具) v2.0.2 免费版
  • Oracle EBS 库存期间关闭状态“已关闭未汇总”处理
  • 【成功经验分享】Github Education (Github学生认证)认证
  • 【NLP实践】一、中文短句情感二分类实现并提供RestfulApi服务调用
  • 创建属于自己的github Page主页
  • 数据结构第1问:什么是数据结构?
  • 重做日志-redo log
  • 决策树(Decision Tree)完整解析:原理 + 数学推导 + 剪枝 + 实战
  • 无向图的连通性问题
  • Qt C++ GUI 函数参数速查手册:基础与布局
  • Android 调试桥 (adb) 基础知识点
  • 通过knn算法实现识别数字
  • 【n8n教程笔记——工作流Workflow】文本课程(第一阶段)——5.4 计算预订订单数量和总金额 (Calculating booked orders)
  • nacos连接失败,启动失败常见问题
  • OpenCV-图像预处理③【图像梯度计算、边缘检测算法(如 Canny)、轮廓提取与分析、凸包特征检测,以及 轮廓的外接几何特征(如最小外接矩形、外接圆等)】
  • 硅基计划3.0 学习总结 肆 二叉树 初版
  • [每周一更]-(第148期):使用 Go 进行网页抓取:Colly 与 Goquery 的对比与思路
  • QT---概览
  • 优化Linux高并发:文件描述符与端口范围的协同调优
  • SPSC无锁环形队列技术(C++)
  • FreeRTOS—空闲任务
  • 【Python系列】Flask 应用中的主动垃圾回收
  • idea打开后project窗口未显示项目名称的解决方案
  • LangGraph快速入门项目部署
  • C++ 中实现 `Task::WhenAll` 和 `Task::WhenAny` 的两种方案
  • 从0搭建YOLO目标检测系统:实战项目+完整流程+界面开发(附源码)