对两阶段提交2PC的理解

Posted 做自由的人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对两阶段提交2PC的理解相关的知识,希望对你有一定的参考价值。

    本文是对中两阶段提交2PC的理解,理解,理解。仅仅是用于理解2PC。



    背景描述:

    系统拆分之后,带来的其中一个难题就是怎样看待和解决分布式事务的ACID。比如,业务系统A依赖某个下游中台服务B,两个系统的状态(这里状态定义:对某条数据保持一样的数值)要保持一致,基本的实现逻辑是:业务系统A更新本地业务数据库,然后通过RPC调用通知中台服务B。伪代码如下:

    process in spring transaction:

            (1)业务系统A的逻辑处理;

            (2)业务系统A更新database;

            (3)业务系统A invoke rpc 中台服务B;


    这样实现之后,会带来什么问题呢?当第三步失败之后,整个事务该不该回滚呢?如果回滚了,那么中台服务B处理成功了,但是业务系统处理失败了,此时两个系统状态不一样;如果不会滚,那么业务系统A成功了,但是中台服务B失败了,仍然是不一样。很尴尬的结局:回滚,不正确;不会滚,仍然不正确。

    面对此时的境况,该如何做决策呢?再把问题重新简化描述一下:如果RPC调用失败了,无论怎样做,都是不正确,此时怎么做最合适?

    一句话理解2PC:只许成功,不许失败。(当然,这并不现实)


    如何达到这样的目的呢?我发现这个答案就隐藏在平常的做事规则中。例如,产品PM要做一个东西出来,首先要写一个需求文档,然后交由开发RD去实现。要想最终把这个东西做出来,我们有两种方式去安排这件事情。

    方式1:产品PM费尽脑汁地写一个非常标准的需求文档,RD看这个需求文档直接去开发。

    方式2:产品PM费尽脑汁地写一个非常标准的需求文档,然后安排RD,QA人员去评审,排期,最后RD再根据需求文档去实现。

    对比两种方式,哪一种能把东西做成功的概率更高一些?根据现实处理的方式,针对大项目,方式2更加靠谱一些。因为方式1存在太多的不确定性:RD是否能完全地理解需求,多个RD团队是否能有效配合,互相之间的依赖时间点是否清晰等等。总之,方式1的缺点就是随着项目的扩大,不确定性增大,那么结果的成功率就会变小。


    受这种方式启发,我认为2PC主要优化的就是减少不确定性的出现,从而提高成功率。优化极限就是:只许成功,不许失败。(当然,这并不现实)


    这时候,再回顾一下2PC中存在的概念:prepare消息,commit消息。

prepare消息干什么呢,就是跟各个团队系统协商(评审需求),预占资源(排期),如果排不上,提前通知。

commit消息又干什么呢,既然团队系统都准备完毕了,那就干活吧,相信一定能成功的。(事实是仍然存在延期的可能)


    一个2PC图(排期进度状态管理图),如下:


结论(定性):

  1. 2PC通过 在事前减少不确定性的发生,进而提高成功率,最终减少了不一致状态发生的概率,但是不能100%避免。

  2. 2PC不是从因果逻辑的角度解决问题,而是从优化的方式看待问题。

以上是关于对两阶段提交2PC的理解的主要内容,如果未能解决你的问题,请参考以下文章

让您轻松理解分布式事务解决方案之2PC

浅谈mysql的两阶段提交协议

使用 Atomikos 的两阶段提交 (2PC) 配置

知识贴:分布式事务的两阶段提交协议(2PC)

Paxos 与两阶段提交

2PC两阶段提交协议