分布式事务中2PC与3PC的区别

2023-10-27

2017-04-02 19:46  442人阅读  评论(0)  收藏  举报
  分类:

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

协调者

在分布式系统中,每一个机器节点虽然都能明确的知道自己执行的事务是成功还是失败,但是却无法知道其他分布式节点的事务执行情况。因此,当一个事务要跨越多个分布式节点的时候(比如,淘宝下单流程,下单系统和库存系统可能就是分别部署在不同的分布式节点中),为了保证该事务可以满足ACID,就要引入一个协调者(Cooradinator)。其他的节点被称为参与者(Participant)。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务进行提交。

二阶段提交协议(2PC)

二阶段提交协议主要分为来个阶段:准备阶段和提交阶段。

在日常生活中其实是有很多事都是这种二阶段提交的,比如西方婚礼中就经常出现这种场景:

牧师:”你愿意娶这个女人吗?爱她、忠诚于她,无论她贫困、患病或者残疾,直至死亡。Doyou(你愿意吗)?”

新郎:”Ido(我愿意)!”

牧师:”你愿意嫁给这个男人吗?爱他、忠诚于他,无论他贫困、患病或者残疾,直至死亡。Doyou(你愿意吗)?”

新娘:”Ido(我愿意)!”

牧师:现在请你们面向对方,握住对方的双手,作为妻子和丈夫向对方宣告誓言。

新郎:我——某某某,全心全意娶你做我的妻子,无论是顺境或逆境,富裕或贫穷,健康或疾病,快乐或忧愁,我都将毫无保留地爱你,我将努力去理解你,完完全全信任你。我们将成为一个整体,互为彼此的一部分,我们将一起面对人生的一切,去分享我们的梦想,作为平等的忠实伴侣,度过今后的一生。

新娘:我全心全意嫁给你作为你的妻子,无论是顺境或逆境,富裕或贫穷,健康或疾病,快乐或忧愁,我都将毫无保留的爱你,我将努力去理解你,完完全全信任你,我们将成为一个整体,互为彼此的一部分,我们将一起面对人生的一切,去分享我们的梦想,作为平等的忠实伴侣,度过今后的一生。

上面这个比较经典的桥段就是一个典型的二阶段提交过程。

首先协调者(牧师)会询问两个参与者(二位新人)是否能执行事务提交操作(愿意结婚)。如果两个参与者能够执行事务的提交,先执行事务操作,然后返回YES,如果没有成功执行事务操作,就返回NO。

当协调者接收到所有的参与者的反馈之后,开始进入事务提交阶段。如果所有参与者都返回YES,那就发送COMMIT请求,如果有一个人返回NO,那就返送roolback请求。

值得注意的是,二阶段提交协议的第一阶段准备阶段不仅仅是回答YES or NO,还是要执行事务操作的,只是执行完事务操作,并没有进行commit还是roolback。和上面的结婚例子不太一样。如果非要举例的话可以理解为男女双方交换定情信物的过程。信物一旦交给对方了,这个信物就不能挪作他用了。也就是说,一旦事务执行之后,在没有执行commit或者roolback之前,资源是被锁定的。这会造成阻塞。


2PC存在的问题

下面我们来分析下2PC存在的问题。

这里暂且不谈2PC存在的同步阻塞、单点问题、脑裂等问题(上篇文章中有具体介绍),我们只讨论下数据一致性问题。作为一个分布式的一致性协议,我们主要关注他可能带来的一致性问题的。


2PC在执行过程中可能发生协调者或者参与者突然宕机的情况,在不同时期宕机可能有不同的现象。


情况一:协调者挂了,参与者没挂

这种情况其实比较好解决,只要找一个协调者的替代者。当他成为新的协调者的时候,询问所有参与者的最后那条事务的执行情况,他就可以知道是应该做什么样的操作了。所以,这种情况不会导致数据不一致。


情况二:参与者挂了,协调者没挂

这种情况其实也比较好解决。如果协调者挂了。那么之后的事情有两种情况:

  • 第一个是挂了就挂了,没有再恢复。那就挂了呗,反正不会导致数据一致性问题。

  • 第二个是挂了之后又恢复了,这时如果他有未执行完的事务操作,直接取消掉,然后询问协调者目前我应该怎么做,协调者就会比对自己的事务执行记录和该参与者的事务执行记录,告诉他应该怎么做来保持数据的一致性。


情况三:参与者挂了,协调者也挂了

这种情况比较复杂,我们分情况讨论。

  • 协调者和参与者在第一阶段挂了。

    • 由于这时还没有执行commit操作,新选出来的协调者可以询问各个参与者的情况,再决定是进行commit还是roolback。因为还没有commit,所以不会导致数据一致性问题。
  • 第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前并没有接收到协调者的指令,或者接收到指令之后还没来的及做commit或者roolback操作。

    • 这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况。只要有机器执行了abort(roolback)操作或者第一阶段返回的信息是No的话,那就直接执行roolback操作。如果没有人执行abort操作,但是有机器执行了commit操作,那么就直接执行commit操作。这样,当挂掉的参与者恢复之后,只要按照协调者的指示进行事务的commit还是roolback操作就可以了。因为挂掉的机器并没有做commit或者roolback操作,而没有挂掉的机器们和新的协调者又执行了同样的操作,那么这种情况不会导致数据不一致现象。
  • 第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。

    • 这种情况下,新的协调者被选出来之后,如果他想负起协调者的责任的话他就只能按照之前那种情况来执行commit或者roolback操作。这样新的协调者和所有没挂掉的参与者就保持了数据的一致性,我们假定他们执行了commit。但是,这个时候,那个挂掉的参与者恢复了怎么办,因为他之前已经执行完了之前的事务,如果他执行的是commit那还好,和其他的机器保持一致了,万一他执行的是roolback操作那?这不就导致数据的不一致性了么?虽然这个时候可以再通过手段让他和协调者通信,再想办法把数据搞成一致的,但是,这段时间内他的数据状态已经是不一致的了!

所以,2PC协议中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。

为了解决这个问题,衍生除了3PC。我们接下来看看3PC是如何解决这个问题的。

三阶段提交协议(3PC)

3PC最关键要解决的就是协调者和参与者同时挂掉的问题,所以3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommitPreCommitDoCommit三个阶段。在第一阶段,只是询问所有参与者是否可可以执行事务操作,并不在本阶段执行事务操作。当协调者收到所有的参与者都返回YES时,在第二阶段才执行事务操作,然后在第三阶段在执行commit或者rollback。

这里再举一个生活中类似三阶段提交的例子:

班长要组织全班同学聚餐,由于大家毕业多年,所以要逐个打电话敲定时间,时间初定10.1日。然后开始逐个打电话。

班长:小A,我们想定在10.1号聚会,你有时间嘛?有时间你就说YES,没有你就说NO,然后我还会再去问其他人,具体时间地点我会再通知你,这段时间你可先去干你自己的事儿,不用一直等着我。(协调者询问事务是否可以执行,这一步不会锁定资源

小A:好的,我有时间。(参与者反馈

班长:小B,我们想定在10.1号聚会……不用一直等我。

班长收集完大家的时间情况了,一看大家都有时间,那么就再次通知大家。(协调者接收到所有YES指令

班长:小A,我们确定了10.1号聚餐,你要把这一天的时间空出来,这一天你不能再安排其他的事儿了。然后我会逐个通知其他同学,通知完之后我会再来和你确认一下,还有啊,如果我没有特意给你打电话,你就10.1号那天来聚餐就行了。对了,你确定能来是吧?(协调者发送事务执行指令,这一步锁住资源。如果由于网络原因参与者在后面没有收到协调者的命令,他也会执行commit

小A顺手在自己的日历上把10.1号这一天圈上了,然后跟班长说,我可以去。(参与者执行事务操作,反馈状态

班长:小B,我们觉得了10.1号聚餐……你就10.1号那天来聚餐就行了。

班长通知完一圈之后。所有同学都跟他说:”我已经把10.1号这天空出来了”。于是,他在10.1号这一天又挨个打了一遍电话告诉他们:嘿,现在你们可以出门拉。。。。(协调者收到所有参与者的ACK响应,通知所有参与者执行事务的commit

小A,小B:我已经出门拉。(执行commit操作,反馈状态

3PC为什么比2PC好?

直接分析协调者和参与者都挂的情况。

  • 第二阶段协调者和参与者挂了,挂了的这个参与者在挂之前已经执行了操作。但是由于他挂了,没有人知道他执行了什么操作。

    • 这种情况下,当新的协调者被选出来之后,他同样是询问所有的参与者的情况来觉得是commit还是roolback。这看上去和二阶段提交一样啊?他是怎么解决一致性问题的呢?

    • 看上去和二阶段提交的那种数据不一致的情况的现象是一样的,但仔细分析所有参与者的状态的话就会发现其实并不一样。我们假设挂掉的那台参与者执行的操作是commit。那么其他没挂的操作者的状态应该是什么?他们的状态要么是prepare-commit要么是commit。因为3PC的第三阶段一旦有机器执行了commit,那必然第一阶段大家都是同意commit。所以,这时,新选举出来的协调者一旦发现未挂掉的参与者中有人处于commit状态或者是prepare-commit的话,那就执行commit操作。否则就执行rollback操作。这样挂掉的参与者恢复之后就能和其他机器保持数据一致性了。(为了简单的让大家理解,笔者这里简化了新选举出来的协调者执行操作的具体细节,真实情况比我描述的要复杂)

简单概括一下就是,如果挂掉的那台机器已经执行了commit,那么协调者可以从所有未挂掉的参与者的状态中分析出来,并执行commit。如果挂掉的那个参与者执行了rollback,那么协调者和其他的参与者执行的肯定也是rollback操作。

所以,再多引入一个阶段之后,3PC解决了2PC中存在的那种由于协调者和参与者同时挂掉有可能导致的数据一致性问题。

3PC存在的问题

在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。

所以,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式事务中2PC与3PC的区别 的相关文章

  • 解决miner.start() 返回null

    下面我列举了三种解决方案 前面两张是某两位大佬试出来的 第三种是我蒙出来的 第一种解决方案 转载自 http mp weixin qq com s AB9vj1EzOgWT7JyryfQhDg 问题场景 最近技术群中的朋友经常问到这样的问题
  • 前端在html页面之间传递参数的方法

    概念图 目标 前端在html页面之间传递参数的方法 项目中经常会出现的一种情况 有一个列表 比如商品列表 点击列表中的某一项商品 跳转至详情页面 跳转页面时 我们需要传递一个参数过去 这样我们才能通过这个参数进行数据请求 然后根据后台返回的
  • CNN(卷积神经网络)在自然语言处理中的应用

    本文参考自Convolutional Neural Networks for Sentence Classification 结尾处放上传送门 用传统方法进行文本分类任务时 通常将一篇文档所对应的tf idf 向量作为模型的特征输入 但是这
  • Python-求排列组合的方法

    1 调用 scipy 计算排列组合的具体数值 from scipy special import comb perm A perm 3 2 out A 6 0 C comb 3 2 out C 3 0 2 调用 itertools 获取排列
  • systemd 服务配置文件编写

    systemd service 简介 Systemd Service 是 systemd 提供的用于管理服务启动 停止和相关操作的功能 它极大的简化了服务管理的配置过程 用户只需要配置几项指令即可 相比于 SysV 的服务管理脚本 用户不需
  • 【mmdetection 】analyze_logs.py等工具测试

    绘制一些运行的分类损失 python tools analyze logs py plot curve work dirs faster rcnn r50 fpn 1x 20200306 175509 log json keys loss
  • 计算机主板南桥的作用,主板南桥是什么,主板南桥芯片在哪?

    主板南桥是什么 主板南桥芯片在哪 笔者稍懂一点电脑硬件 看到网友提问相关方面的问题 很是乐意回答 网络本来就崇尚人人为我 我为人人么 自己这点半瓶水的知识 本来就拜网上高手的科普文章所赐 所以遇到 像主板南桥是什么 主板南桥芯片在哪这类问题
  • QT学习:实现简单的登录登出界面功能

    在设计实现一个系统的时候 用户登录界面的设计可以说是必不可少的环节 而用户登录界面的实现说到底就是不同窗口之间的切换 在继续下面的工作之前 你首先要添加一个新的Qt设计师界面类 记住要选择Dialog without Buttons 否则方
  • Invalid block tag on line 129: ‘get_tag_list‘, expected ‘endblock‘. Did you forget to register or lo

    Django gt python manage py runserver时报错 Invalid block tag on line 129 get tag list expected endblock Did you fo rget to
  • 手把手教Electron+vue,打包vue项目,打包成桌面程序。

    1 现如今前端框架数不胜数 尤其是angular vue吸引一大批前端开发者 在这个高新技术快速崛起的时代 自然少不了各种框架的结合使用 接下来是介绍electron vue的结合使用 2 Electron是什么 对于我来说Electron
  • 最适合读研究生的城市,有你想去的城市吗?

    最适合读研究生的城市 有你想去的城市吗 有没有一座城市让你心生向往 你会因为城市而去选择院校还是因为学校爱上一座城 下面我们就来看一下人气最高 最适合读研的城市 1 北京 北京作为我国的首都 是全国政治文化中心 人称帝都 北京名校众多 既是
  • UML在软件开发各个阶段的应用

    一 UML5个互联视图 UML Unified Modeling Language 中常用5个互联的视图来描述系统的体系结构 如图 1 用例视图 Use case View 由专门描述可被最终用户 分析人员 测试人员看到的系统行为的用例图组
  • Markdown简介

    目录 什么是Markdown Markdown的发展简史 Markdown的基本写法 标题 文本 分隔线 列表 表格 区块 代码段 链接 图片 其他技巧 什么是Markdown Markdown是一种轻量级标记语言 Markdown的写法比
  • web UI 自动化测试:Selenium 语法详解 史上最全

    selenium主要是用来做自动化测试 支持多种浏览器 爬虫中主要用来解决JavaScript渲染问题 模拟浏览器进行网页加载 一 声明浏览器对象 注意点一 Python文件名或者包名不要命名为selenium 会导致无法导入 from s
  • c++ 语法错误 : 缺少“;”(在“*”的前面)

    语法错误 缺少 在 的前面 出现这个错误 我们当然不会考虑简单的原因 就是缺少 在的前面 那么来分析一下可能的不好发现的原因 error C4430 缺少类型说明符 假定为 int 注意 C 不支持默认 int c evan workspa

随机推荐

  • 【mysql】给一张表添加外键的四种方法

    mysql外键 主键 一 添加外键 二 添加主键 一 添加外键 添加外键约束名字一定不能重复 如何添加外键 方法一 直接在属性值后面添加 create table score cscore int 11 st id int 50 refer
  • 关于转换JSON列表错误导致结果出错的问题

    今天修改一个问题 就是不同端封装的不同对象 请求同一个接口 同一个数据 在通用的一个逻辑转换状态中获取到不同的状态的奇葩问题 其实本身两个接口大部分代码是相同的 是直接拷贝过去的 其实就是最后的结果对象参数稍微有点区别 大部分逻辑都是重复的
  • SpringBoot基础入门篇

    文章目录 前言 一 Spring Boot 入门 1 Spring Boot 简介 2 微服务 3 环境准备 1 MAVEN设置 4 Spring Boot HelloWorld 1 创建一个maven工程 jar 2 导入spring b
  • FPGA编程中"打拍"的目的

    版权声明 本文为CSDN博主 qq 33586509 的原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net qq 33586509 article detai
  • quartz 2.3.1源码分析一:创建JobDetail(JobBuilder详解)

    上一篇文章我记录了自己封装的QuartzUtil工具类 同时写了一个quartz骨架项目 以便大家理解使用 点击传送门进入 正文开始 Quartz工具类 创建JobDetail JobBuilder详解 创建CronTrigger Trig
  • 详细前端面试题HTML篇

    CSS篇 JS篇 Vue篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript React 微信小程
  • matlab 遗传优化算法_全局优化

    Building可视库 一起做些更酷的事吧 关注 小库这两天学习有关遗传算法的一些问题 其作为一种全局寻优的智能优化算法 具有很强大的适应性 可以应用于多个领域解决一些最优化的问题 诸如寻路问题 囚犯困境 动作控制 生产调度问题 人工生命模
  • matlab 点云的二进制形状描述子

    目录 一 功能概述 1 算法概述 2 主要函数 3 参考文献 二 代码示例 三 结果展示 四 参数解析 输入参数 名称 值对应参数 输出参数 五 参考链接 本文由CSDN点云侠原创
  • 第七届cuit智能车比赛总结

    作为大一小白 第一次参加比赛 感受到了比赛的氛围 也收获了许多宝贵的经验 1 电磁杆 电磁杆的作用是感应漆包线的位置 给单片机传入数据 使车维持在一定范围内 他的感应部分应用RLC振荡电路 感应到的微弱电流经过一定倍数放大 和滤波电路 最后
  • 多线程详解(一)——创建多线程

    一 进程与线程 1 进程 进程是资源 CPU 内存等 分配的基本单位 它是程序执行时的一个实例 程序运行时系统就会创建一个进程 并为它分配资源 然后把该进程放入进程就绪队列 进程调度器选中它的时候就会为它分配CPU时间 程序开始真正运行 2
  • MyBatis-Plus(二)设置实体类对应的表名、字段名

    设置实体类对应的表名 字段名 一 设置关联的表名 1 默认情况下 如果数据库表是使用标准的下划线命名 并且能对应上实体类的类名 我们就不需要特别去手动匹配 比如有张 user info 表 那么会自动匹配下面这个实体类 Data publi
  • 【硬件】以太网PHY芯片有三个时钟说明

    硬件以太网PHY芯片有三个时钟 对此进行了梳理 PHY芯片时钟的选择 PHY芯片中有3个时钟 Gtx clk Rx clk Tx clk 1 GTX CLK仅使用在GMII模式下 时钟频率为125M 发送数据时的时钟 2 RX CLK在GM
  • Altium Desinger - PCB 3D模型创建导出

    打开绘制好的PCB版图 点击File gt Export gt STEP 3D 输出保存 就可以被solidworks 打开导入 整机文件
  • 上海某高校线上期末题-核酸检测系统C++实现

    上海某高校线上期末题 核酸检测系统C 实现 注意 本博客只是以学习交流和记录学习内容为主 分享自己的一些见解和思路 如有不当之处 请告知 试题内容 考核要求 项目文件地址 在github上开源 https github com hudisc
  • 如何在PADS中添加表面型测试点

    在PCB 设计中 我们经常需要对某些信号线增加一些测试点 以便在产品调试中对其信号进行测试 在PADS Layout POWERPCB 中添加测试点时 默认的是以标准过孔STANDARDVIA 作为测试点 但这是通孔方式的测试点 为了节省测
  • Spring更简单的使用方法

    前面介绍了一些最基本的存储和读取Bean对象的方法 但是在Spring中已经基本不这样使用了 因此这一篇博客就来介绍一下更简单的存储和读取Bean对象的方法而想要更简单的存储和读取最核心的就是使用注解 下面一起来看看吧 目录 一 存储Bea
  • Cherry-Pick

    版权声明 本公众号发布的所有文章 均属于原创 版权归本公众号所有 未经允许 不得转载 一 前言 在实际工作开发中 会遵循标准的 Git Work flow 对待不同的功能 会切出不同的分支进行 coding 所以 基于什么基准分支切出来的功
  • 过采样4:提高ADC分辨率实例(终篇)

    原文来自公众号 工程师看海 公众号后台回复 过采样 有更多资料 这应该是过采样系列的最后一篇文章 经常有同学在使用FPGA 单片机或者DSP进行过采样时没有正确设计代码 导致结果异常 有些结果看似正常 而实际却没有意义 这篇文章涉及到简单的
  • Unity 判断 鼠标/触摸 位置是否在指定Ui上,非射线检测方式。触屏移动物体。

    事出有因 1 项目的触摸点击事件 并且有手指缩放 移动功能 2 unity本身支持touch功能 这个不多说 3 当做手指缩放 移动的时候就要判断touch点位置了 但是如果不加任何判断则会乱套 如 本来想移动A 让A跟随 手指touch
  • 分布式事务中2PC与3PC的区别

    分布式事务中2PC与3PC的区别 2017 04 02 19 46 442人阅读 评论 0 收藏 举报 分类 Java知识 1 版权声明 本文为博主原创文章 未经博主允许不得转载 目录 协调者 在分布式系统中 每一个机器节点虽然都能明确的知