深入理解分布式系统的2PC和3PC

转载自 深入理解分布式系统的2PC和3PC

 

关注我的博客(http://www.hollischuang.com)的人可能都知道,我之前写过一篇文章专门介绍了一下2PC和3PC(详见:关于分布式事务、两阶段提交协议、三阶提交协议)。上一篇文章中主要介绍了下这两种分布式一致性协议的概念、具体提交流程以及优缺点。本文在上篇文章的基础上在深入了解下这两种分布式一致性协议。主要来分析下为什么2PC存在问题,为什么3PC解决了部分2PC存在的问题,以及为什么3PC还存在可能导致数据不一致的情况。

对分布式系统的概念及2PC和3PC不了解的朋友建议先阅读分布式系列文章。

协调者

在分布式系统中,每一个机器节点虽然都能明确的知道自己执行的事务是成功还是失败,但是却无法知道其他分布式节点的事务执行情况。因此,当一个事务要跨越多个分布式节点的时候(比如,淘宝下单流程,下单系统和库存系统可能就是分别部署在不同的分布式节点中),为了保证该事务可以满足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命令并执行回滚的参与者之间存在数据不一致的情况。

参考资料

2PC和3PC一点理解

再谈2PC和3PC

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 百度经纬度 转换为 高德经纬度 谷歌

https://lbs.amap.com/api/webservice/guide/api/convert/#convert https://restapi.amap.com/v3/assistant/coordinate/convert?locations116.481499,39.990475&coordsysgps&outputxml&key<用户的key> https://console.amap.com/dev/key/app https://conso…

方法的重写VS重载

方法的重写&#xff08;override&#xff09; 方法的重写 子类从父类中继承方法&#xff0c;有时&#xff0c;子类需要修改父类中定义的方法的实现&#xff0c;这称做方法的重写(method overriding)。“重写”的概念与“重载”相似&#xff0c;它们均是Java“多态”的技术之一&…

使用阿里云火车票查询接口案例——CSDN博客

首先我们需要一个实体类&#xff0c;专门放火车票信息的封装类&#xff0c;实体类&#xff1a; Train.java: /** * Title: Train.java * Package cn.bdqn.guanMingSys.entity * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * dat…

权衡微服务

很多开发团队已经认识到 微服务架构比单体架构更优越。但是也有其他团队感觉到这是一种消弱生产力的负担。就像任何软件架构&#xff0c;微服务架构同样有利弊。为了能做出一个明智的选择&#xff0c;你必须了解这些应用并将它们运用到你特定的环境中。 微服务的优势 具有边界的…

使用IDM下载,不适用默认浏览器下载

google浏览器是不能够安装的除非有v*p*n&#xff08;&#xff09; Firefox浏览器可以安装js脚本 推荐使用 1 google 扩展 IDMan628 扩展程序里面加 IDMGCExt.crx 2 扩展Tampermonkey 加Tampermonkey.crx 3 点击Tampermonkey 的仪表盘 右上角加按钮 百度网盘直接下载助手…

深入分析事务的隔离级别

转载自 [中级]深入分析事务的隔离级别 本文详细介绍四种事务隔离级别&#xff0c;并通过举例的方式说明不同的级别能解决什么样的读现象。并且介绍了在关系型数据库中不同的隔离级别的实现原理。 在DBMS中&#xff0c;事务保证了一个操作序列可以全部都执行或者全部都不执行&am…

使用阿里云智能翻译接口案例——CSDN博客

/*** * Title: getTranslates* Description: 该方法的主要作用&#xff1a;智能翻译* param 设定文件 * return 返回类型&#xff1a;void * throws*/public void getTranslates(){String host "https://dm-11.data.aliyun.com";String path "/rest/160…

ASP.NET Core 中的那些认证中间件及一些重要知识点

前言 在读这篇文章之间&#xff0c;建议先看一下我的 ASP.NET Core 之 Identity 入门系列&#xff08;ASP.NET Core 之 Identity 入门&#xff08;一&#xff09;&#xff0c;ASP.NET Core 之 Identity 入门&#xff08;二&#xff09;&#xff0c;ASP.NET Core 之 Identity 入…

判断个十百千位之后是否大于20 java——CSDN博客

/*** * Title: test_draw_a_lottery_or_raffle* Description: 该方法的主要作用&#xff1a;输入四位数&#xff0c;各位数数字之和大于20 中奖&#xff0c;否则没中奖* param 设定文件 * return 返回类型&#xff1a;void * throws*/Testpublic void test_draw_a_lotte…

mybatis-plus 错误java.lang.NoClassDefFoundError: org/apache/velocity/context/Context

https://blog.csdn.net/qq_39609151/article/details/82855305 mybatis-plus 错误java.lang.NoClassDefFoundError: org/apache/velocity/context/Context Murphy_fly 2018-09-26 16:41:55 27168 收藏 15 分类专栏&#xff1a; 框架 版权 使用mybatis-plus自动生成文件的时…

向上类型转换VS向下类型转换

子类转换成父类时的规则: 将一个父类的引用指向一个子类的对象&#xff0c;称为向上转型(upcasting)&#xff0c;自动进行类型转换。此时通过父类引用调用的方法是子类覆盖或继承父类的方法&#xff0c;不是父类的方法。 此时通过父类引用变量无法调用子类特有的方法&#xff…

彻底理解数据库事务

转载自 彻底理解数据库事务 事务 事务(Transaction)&#xff0c;一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在计算机术语中&#xff0c;事务通常就是指数据库事务。 概念 一个数据库事务通常包含对数据库进行…

.NET 使用 RabbitMQ 图文简介

前言 最近项目要使用RabbitMQ&#xff0c;园里里面已经有很多优秀的文章&#xff0c;Rabbitmq官网也有.net实例。这里我尝试下图文并茂之形式记录下使用的过程。 安装 RabbitMQ是建立在erlang OTP平台下&#xff0c;因此在windows下需要下载并安装以下两个组件&#xff1a; 1. …

使用java交换两个数——CSDN博客

/*** * Title: test_exchange* Description: 该方法的主要作用&#xff1a;交换两个数* param 设定文件 * return 返回类型&#xff1a;void * throws*/Testpublic void test_exchange(){int num1 10;int num2 20;int exchange 0;System.out.println("原来的…

Springboot+MyBatis-plus+postgresSQL 的整合

https://blog.csdn.net/xuxiannian/article/details/99625085 SpringbootMyBatis-pluspostgresSQL 的整合 禛陌 2019-08-15 12:20:10 6752 收藏 7 分类专栏&#xff1a; 技术相关 文章标签&#xff1a; SpringbootMyBatis-pluspostgresSQL 版权 磨叨一下 MyBatis-plus 请…

String中的compareTo()方法

compareTo()方法 String类中的compareTo()方法将返回两个字符串对象的比较结果&#xff0c;若相等&#xff0c;返回0。不相等时&#xff0c;从两个字符串第1个字符开始比较&#xff0c;返回第一个不相等的字符差&#xff1b;另一种情况&#xff0c;较长字符串的前面部分恰巧是较…

使用Senparc.Weixin.WxOpen开发高可用的微信小程序

Senparc.Weixin SDK介绍 Senparc.Weixin SDk是目前.net平台上使用率最高的微信SDK&#xff0c;除硬件平台暂未发布以外覆盖了所有微信平台模块&#xff0c;自2013年免费开源起已经持续更新了4年&#xff0c;是GitHub上目前Star和Fork数最多的中国C#开源项目。 目前大多数模块都…

java使用循环案例——CSDN博客

/*** * Title: test_while* Description: 该方法的主要作用&#xff1a;while循环&#xff0c;输出100个我爱编程* param 设定文件 * return 返回类型&#xff1a;void * throws*/Testpublic void test_while(){int i 1;while (i<100) {System.out.println("第&…

Java中的事务——JDBC事务和JTA事务

转载自 Java中的事务——JDBC事务和JTA事务 我的博客中曾经关于事务有过很多讨论&#xff0c;之前的事务介绍基本都是数据库层面的事务&#xff0c;本文来介绍一下J2EE中和事务相关的内容&#xff0c;在阅读本文之前&#xff0c;希望读者对分布式有一定的了解。 关于事务的基础…