2PC/3PC一致性协议

前言
在上一篇文章从ACID到CAP/BASE中我们介绍了CAP理论,其中最重要的一点就是一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个基本需求,最多只能同时满足其中的两项;而一般都会在一致性和可用性之间进行权衡,于是产生了一系列的一致性协议。

在介绍有哪些一致性协议之前,我们先来看看一致性模型

一致性模型
一致性模型大体上可以划分为2个大类:强一致性和弱一致性
弱一致性可以划分为:最终一致性,因果一致性,读你所写一致性,会话一致性,单调读一致性,单调写一致性
其中最常见的两项就是:强一致性和最终一致性
强一致性:新的数据一旦写入,在任意副本任意时刻都能读到新值
最终一致性:当你写入一个新值后,有可能读不出来,但在某个时间窗口之后保证最终能读出来

本文介绍的2PC/3PC是属于强一致性协议

2PC/3PC
2PC/3PC全称:Two/Three Phase Commit,中文名叫叫两阶段/三阶段提交;为了使基于分布式系统架构下的所有节点在进行事务处理的过程中能够ACID特性而设计的一种算法,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交两阶段提交的算法如下:
第一阶段:提交事务阶段(投票阶段)
1.事务询问:协调者会问所有的参与者结点,是否可以执行提交操作
2.执行事务:各个参与者执行事务操作 如:资源上锁,将Undo和Redo信息记入事务日志中
3.参与者向协调者反馈事务询问的响应:如果参与者成功执行了事务操作,反馈给协调者Yes响应,否则No响应

第二阶段:执行事务提交(执行阶段)
假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务提交
1.发送提交请求:协调者向参与者发送Commit请求
2.事务提交:参与者接受到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放事务资源
3.反馈事务提交结果:参与者在完成事务提交之后,向协调者发送Ack消息
4.完成事务:协调者接受到所有参与者反馈的Ack消息后,完成事务

假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无接收到所有参与者的反馈信息,那么就会中断事务
1.发送回滚请求:协调者向参与者发送Rollback请求
2.事务回滚:参与者利用Undo信息来执行事务回滚,并释放事务资源
3.反馈事务回滚结果:参与者在完成事务回滚之后,向协调者发送Ack消息
4.中断事务:协调者接收到所有参与者反馈的Ack消息之后,中断事务

网上看来的西方教堂结婚一个桥段很好的描述了2PC协议:
1.牧师分别问新郎和新娘:你是否愿意……不管生老病死……(投票阶段)
2.当新郎和新娘都回答愿意后(锁定一生的资源),牧师就会说:我宣布你们……(执行阶段)

2PC存在的问题
1.阻塞问题
二阶段提交的第一阶段中,协调者需要等待参与者的响应,如果没有接收到任意参与者的响应,这时候进入等待状态,而其他正常发送响应的参与者,将进入阻塞状态,将无法进行其他任何操作,只有等待超时中断事务,极大的限制了系统的性能。
2.单点问题
协调者处于一个中心的位置,一旦出现问题,那么整个二阶段提交将无法运转,更为严重的是,如果协调者在阶段二中出现问题的话,那么其他参与者将会一直处于锁定事务资源的状态中,将无法继续完成操作
以上提到的2个问题都在3PC中得到了解决
1.解决阻塞问题:将2PC中的第一阶段一分为二,提供了一个CanCommit阶段,此阶段并不锁定资源,这样可以大幅降低了阻塞概率
2.解决单点问题:在参与者这边也引入了超时机制

3PC
3PC是2PC的改进版本,将2PC的第一阶段:提交事务阶段一分为二,形成了CanCommit、PreCommit和doCommit三个阶段组成的事务处理协议,具体看一张流程图(来源网上):
three-phase_commit_diagram

三段提交的核心理念是:在询问的时候并不锁定资源,除非所有人都同意了,才开始锁资源。
3PC具体的流程步骤就不在描述了,在二阶段的基础上加了事务询问的过程(CanCommit)

3PC虽然解决了2PC存在的2个问题,但是不管是2PC还是3PC都存在数据一致性的问题:
2PC:比如协调者在只给部分参与者发送了Commit请求,那就会出现部分参与者执行了Commit,部分没有提交,出现不一致问题。
3PC:一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态,但是这种机制也会导致数据一致性问题。

协议的应用
两阶段提交协议在主流开发语言平台,数据库产品中都有广泛应用和实现的,下面来介绍一下XOpen组织提供的DTP模型图:
20160702104131762

DTP全称是Distributed Transaction Process,即分布式事务模型。
TM(Transaction Manager):事务管理器 协调者
RM(Resource Manager):资源管理器 参与者(数据库)
AP(Application Program):应用程序
XA协议:是TM(事务管理器)和RM(资源管理器)之间的接口

目前主流的关系型数据库产品都是实现了XA接口的,JTA(Java Transaction API)是符合X/Open DTP模型的,事务管理器和资源管理器之间也使用了XA协议。 本质上也是借助两阶段提交协议来实现分布式事务的,看看XA事务成功模型图:
20160702104220621
是不是和2PC流程很像
在JavaEE平台下,WebLogic、Webshare等主流商用的应用服务器提供了JTA的实现和支持。而在Tomcat下是没有实现的,这就需要借助第三方的框架Jotm、Automikos等来实现。

总结
2PC/3PC能够很好的提供强一致性和强事务性,但相对来说延迟比较高,比较适合传统的单体应用,在同一个方法中存在跨库操作的情况,不适合高并发和高性能要求的场景。

参考文章:http://coolshell.cn/articles/10910.html