热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

分布式系统一致性专题:3PC协议的优化和问题

本文介绍了分布式系统一致性专题中的3PC协议,该协议是对2PC协议的优化和改进。文章详细解释了3PC协议的三个阶段:CanCommit、PreCommit和DoCommit,并分析了每个阶段可能出现的情况和处理方式。同时,文章也指出了3PC协议存在的问题,如参与者超时机制可能导致数据不一致等。总体来说,3PC协议在优化和改进方面取得了一定效果,但仍需继续努力解决数据不一致问题。
导读 分布式系统一致性专题本期该写 3PC 协议了,上周太忙没有时间更新,就拿了之前的旧文章做了一些调整重发了一下,还望各位读者海涵。后面大约还有3期:Paxos 协议、Raft 协议等,先预热一下。

分布式系统一致性专题本期该写 3PC 协议了,上周太忙没有时间更新,就拿了之前的旧文章做了一些调整重发了一下,还望各位读者海涵。后面大约还有3期:Paxos 协议、Raft 协议等,先预热一下。温馨提示:本篇文章并不会枯燥,换了个画图工具,对于我这种建筑专业出身的IT狗来说,画图简直是最开心的事情了,所以放心看吧!

分布式系统一致性之3PC协议浅谈

图(网络)|猎户座大星云

之前文章中提到了 2PC 协议存在的协调者单点、参与者阻塞超时、网络分区、容错性等问题,这些在某些程度上是做优化和调整的,并不是致命问题。我们对 2PC 协议的异常情况做了拆解,但是那是个m*n的组合问题,我们尽量去分析主要矛盾,于是发现在协调者和唯一接收指令的参与者都出现不可恢复宕机时,即使后面选举了新的协调者,仍然可能出现数据的不一致性。3PC 的出现可能是多种因素促成的。但是基本上可以确定 3PC 将对 2PC 存在的问题进行修正和优化,但是这样并不意味着 3PC 不会引入新的问题。本文将从 3PC 的协议过程来阐述这两大块内容:

分布式系统一致性之3PC协议浅谈

3PC协议 Three-Phase-Commit 又称三阶段提交协议,相比 2PC 协议增加了一个阶段,因此我们普遍把 3PC 协议看作是 2PC 协议的改进版本。3PC 协议将 2PC 协议的准备阶段一分为二,从而形成了三个阶段:

分布式系统一致性之3PC协议浅谈

协调者和参与者等待超时情况单独说,先看正常情况的基本过程,要不然容易混淆。

在2PC准备阶段中,协调者向参与者发送指令后,参与者如果具备执行条件,则获取锁并执行动作,只不过未真正提交,可以认为参与者就差临门一脚了,还得等协调者信号。如果是 commit 信号那还好,如果是 rollback 信号,那么对于一些本地执行了动作的参与者来说白白浪费了,所以从这个角度来说,2PC 有点激进了,但是这么做也是有原因的,在复杂的网络环境中多一轮交互意味着性能的损耗。3PC来说更加合理,先由协调者向参与者发送询问信号,兄弟们有档期吗??然后开始收集反馈,相比来说更加轻量。这个阶段参与者并不真实获取锁占用资源,只是对自身执行事务状态的检查,查看是否具备执行事务的条件,进而回复询问。

根据参与者对询问的反馈,在 CanCommit 阶段可能出现的两情况:

分布式系统一致性之3PC协议浅谈

图:询问阶段所有参与者均具备执行事务条件

分布式系统一致性之3PC协议浅谈

图:询问阶段存在不具备条件的参与者

第二个阶段的具体动作取决于第一个阶段的结果,因此可以分为两种情况:

在第一阶段所有参与者都 Ready,那么协调者就会向参与者发送本地执行的相关指令,这部分和 2PC 的第一阶段非常相似,参与者收到指令后进行本地事务执行,并记录日志,并且对处理结果反馈到协调者,来做决策。过程中参与者可能成功或者失败,出现了两种情况:

分布式系统一致性之3PC协议浅谈

图:PreCommit阶段参与者均反馈成功

分布式系统一致性之3PC协议浅谈
图:PreCommit阶段参与者中存在失败实例

在第一阶段如果存在参与者不 Ready 的情况,那么协调者就会发送信号给所有参与者,告知本次事务取消了,该干啥干啥吧,对参与者来说损失并不大,因为本质上参与者并没有做什么事情。

分布式系统一致性之3PC协议浅谈

这是 3PC 的第三个阶段和2PC的第二个阶段类似,同样的 DoCommit 执行具体动作取决于第二阶段 PreCommit 的结果,因此仍然分为两种情况:

在 PreCommit 之后参与者全部完成本地事务执行但是没有提交,并且都给协调者 ACK 回复,这时协调者认为万事俱备只欠东风了,在 DoCommit 阶段协调者向参与者发送提交指令,参与者收到之后开始执行本地提交,并反馈结果,最终完成这次事务,Cool!

分布式系统一致性之3PC协议浅谈

协调者在第二个阶段 PreCommit 收到参与者的反馈后,发现存在部分参与者无法执行事务的情况,这时就决定告诉其他参与者本地回滚,释放资源,取消本次事务。

分布式系统一致性之3PC协议浅谈

我们前面提到 3PC 要解决 2PC 的参与者阻塞超时问题,在2PC中参与者比较痴情,协调者不给信号会长时间阻塞,不释放资源,这样别人也没法处理其他事情,确实不太好,看来 2PC 还是太依赖协调者了。3PC 认为网络超时是普遍发生的情况,如果参与者在一种大概率确定的状态下执行一些动作也是被允许的,将在外军令有所不受。3PC 的超时处理可能发生在 PreCommit 和 DoCommit 阶段,来看个图:

分布式系统一致性之3PC协议浅谈

协调者和参与者之间可能存在较大的网络延时,或者协调者出现故障,或者出现网络分区等情况,参与者并不会傻等,在超过设定时间之后,参与者就继续做之前的事情了,因为好像被大哥鸽了,只能该干啥干啥,这也是正确的决策。

在 CanCommit 和 PreCommit 之后,参与者认为大家都对齐了都是棒棒的,如果参与者在设定时间内并没有收到协调者的 DoCommit 指令,那么就本地执行提交完成这次事务,因为参与者揣测大哥的意思大概率也是让我们提交,干等着也不是办法,回滚可能和大家不一样,抉择之下参与者选择提交事务。

3PC协调者的等待超时处理和2PC基本上是一样的,无论在哪个阶段超时都认为不具备条件,进行 abort 或者 rollback 操作,这个非常好理解。

可以看到3PC协议中参与者不再过度依赖协调者的指令信号,而是有了自己的相对独立性,可以根据当前所处的状态来进行自我决策。避免了2PC中的阻塞等待带来的资源浪费情况,确实是个不错的优化,但是我们并不能完全保证这种优化就都是完全正确的呀!换句话说3PC解决了2PC的bug,但是不代表3PC没有引入新的bug。

前面我们说到3PC协议的一个重要作用就是要对2PC协议的改进和优化,从上面的过程分析可知确实做了一些优化,但是仍然不可避免出现了新的问题。

2PC协议在某些场景下数据不一致问题,那么3PC有没有这种问题呢?答案是有,根源是新加的参与者超时机制。比如参与者A因为自身网络问题,在设定时间内未收到协调者的信号,这时参与者A基于之前的状态执行了Commit操作,提交了事务,这种情况确实会发生,根据真实的协调者信号是commit还是rollback会出现不同的结果。

如果协调者发送的是Commit指令,就和参与者A独自决策结果一致,没啥问题。如果协调者在DoCommit阶段发送的是rollback指令,那么超时的参与者A由于执行了本地事务提交,从而和其他收到指令执行rollback的参与者的数据不一致。

分布式系统一致性之3PC协议浅谈

我们知道2PC协议的决策结果初始阶段只有决策者知道,只有在它发送了决策解决才有参与者知道,这样就存在决策结果丢失的情况。假如协调者挂掉,新协调者可以咨询所有的参与者来确定决策状态,根据所有参与者的情况来确定,但是万一真理掌握在少数人手中呢?

假如有10个参与者,9个都是正常的,1个状态未知(先叫做A吧),10个参与者都向协调者发送了反馈,如果A反馈的是Not Ready信号,其他9个都是Ready信号。协调者汇总结果决策出不具备执行条件,开始向所有参与者发送rollback,恰好第一个收到信号的是A机器,协调者挂了,A收到信号后也挂了。新的协调者询问了其余9个都是OK,新的协调者就认为具备条件了从而发送Commit信号,这样就出现了不一致。

这个过程和清宫剧中皇帝立储很像嘛,皇帝把结果挂在朝堂的牌匾之上,假定诏书消失了且皇帝挂了,那么结果就不得而知了,智囊团在没有私心的前提下就需要考察所有的侯选人的情况来确定,这样就可能出现不一致。

在3PC中仍然存在只有1台机器收到指令然后挂掉的情况,但是如果出现在前置阶段,对整个结果是没有影响的,因为会被取消并且参与者并没有本地执行。

现在看3PC的思想是把做重大动作时的决策结果透明化统一化,产生的影响也就非常小了,因此PreCommit阶段的状态是明确的。

我们需要把决策结果透明化,让所有参与者都知道决策结果,3PC的PreCommit阶段对齐了结果,只要有1台还活着,整个事务的状态就是确定的,毕竟所有参与者全挂的情况概率非常低。

分布式系统一致性之3PC协议浅谈

3PC协议是对2PC协议的优化和改进,通过将2PC的准备阶段一分为二:CanCommit和PreCommit,整个过程中下一阶段的流转要取决于上一个阶段的结果,流转简图:

分布式系统一致性之3PC协议浅谈

经过CanCommit和PreCommit阶段后,参与者之间对齐并保留了决策结果,避免2PC协议极端情况决策结果的错误缺失,是个比较好的做法。

2PC协议只有协调者有超时机制,3PC协议对参与者也引入了超时机制,在不同的阶段进行不同的超时处理,但是由于网络波动和网络分区存在让参与者的超时处理带来新的不确定性,甚至可能出现数据不一致。

3PC协议增加一轮询问阶段所以整个交互过程比2PC更长了,性能相比2PC是会有一些下降的,但是3PC协议对于网络分区等情况也并没有处理地很好。

总体来说,3PC相比2PC做了很多改进有一定的效果,但是仍然存在数据不一致问题,还需继续努力。


推荐阅读
  • Elasticsearch1Elasticsearch入门1.1Elasticsearch术语1.1.16.0以前的Elasticsearch术语1.1.26.0以后的Elasti ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文介绍了在使用TortoiseSVN的Repo-browser浏览SVN时出现的错误,以及解决方法。文章提到了卸载当前版本、安装较低版本、使用更下一层的路径等解决方案。同时指出该问题可能是客户端与SVN服务端不匹配造成的,且服务端无法升级更高的SVN版本。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 先看一段错误日志:###Errorqueryingdatabase.Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransie ... [详细]
  • 解决php错误信息不显示在浏览器上的方法
    本文介绍了解决php错误信息不显示在浏览器上的方法。作者发现php中的各种错误信息并不显示在浏览器上,而是需要在日志文件中查看。为了解决这个问题,作者提供了一种解决方式:通过修改php.ini文件中的display_errors参数为On,并重启服务。这样就可以在浏览器上直接显示php错误信息了。 ... [详细]
author-avatar
纯洁的老宁同志
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有