为了解决分布式一致性问题,涌现出一大批经典一致性协议和算法,最著名的就是二阶段提交协议,三阶段提交协议和Paxos算法。
文章目录- 第二章 一致性协议
- 2.1 2PC 与 3PC
- 2.1.1 2PC
- 阶段一:提交事务请求
- 阶段二:执行事务提交
- 执行事务提交
- 中断事务
- 优缺点
- 同步阻塞
- 单点问题
- 数据不一致
- 太过保守
- 3PC
- 阶段一:CanCommit
- 阶段二:PreCommit
- 执行事务预提交
- 中断事务
- 阶段三:doCommit
- 执行提交
- 中断事务
- 优缺点
- 2.2 Paxos 算法
- 小结
在分布式系统中,每个节点只知道自己进行事务的过程中结果是失败还是成功,但无法直接获取其他分布式节点的操作结果。因此,为了保持一个事务需要跨越多个节点并保持ACID特性,**就需要引入一个称为"协调者"(Coordinator)组件来统一调度所有节点的执行逻辑,而这些被调度的就是分布式节点被称为"参与者"(Participant)。**协调者负责调度参与者的行为,并最终决定是否把事务真正进行提交。基于这个思想衍生出了二阶段提交协议和三阶段提交协议。
2.1.1 2PC2PC (Two-Phase Commit),即二阶段提交,目前大多数关系型数据库都是采用二阶段提交协议来完成分布式事务处理的,利用该协议能够非常方便完成所有分布式事务参与者的协调,统一决定事务的提交或回滚,从而能够有效保证分布式的一致性。
阶段一:提交事务请求-
事务询问
协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
-
执行事务
各参与者节点执行事务操作,并将 Undo 和 Redo 信息记入事务日志中。
-
各参与者向协调者反馈事务询问的响应。
如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行,否则反馈给No响应。
二阶段提交协议的阶段一也被称为"投票阶段",即协调者组织各参与者对一次事务操作的投票表态过程,投票表明是否要继续执行接下去的事务提交操作。
阶段二:执行事务提交在阶段二中,协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作。
执行事务提交 假如协调者从所有的参与者获得反馈都是Yes响应,那么就会执行事务提交。
-
发送提交请求
协调者向所有参与者节点发出commit请求。
-
事务提交
参与者接收到 commit 请求后,会正式执行事务提交操作,并在完成提交操作,并在完成提交之后释放整个事务执行占用的事务资源。
-
反馈事务提交结果
参与者在完成事务提交之后,向协调者发送Ack消息。
-
完成事务
协调者接收到所有参与者反馈的Ack消息后,完成事务。
假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈响应,那么就会中断事务。
-
发送回滚请求。
协调者向所有参与者节点发出Rollback请求。
-
事务回滚
参与者接收到 Rollback 请求后,会利用其在阶段一中记录的Undo信息来执行事务回滚操作,并在回滚后释放资源。
-
反馈事务回滚事务
参与者完成回滚后,向协调者发送Ack消息。
-
中断事务
协调者接收到所有参与者反馈的Ack消息后,完成事务中断。
简单来讲,二阶段提交将一个事务处理过程分为了投票和执行两个阶段,其核心是对每个事务都采用 先尝试后提交 的处理方式,因此也可以将二阶段协议看作一个强一致性协议。
优缺点优点:原理简单,实现方便。
缺点:同步阻塞、单点问题、脑裂、太过保守
同步阻塞这会极大限制分布式系统性能。在二阶段提交的过程中,各个参与者在等待其他参与者响应过程中,无法进行其他任何操作。
单点问题协调者在二阶段协议中起到了尤为重要的角色,因此如果协调者出现了问题,提交流程就会无法运转,那么其他参与者就会一直处于锁定事务资源的状态中,无法继续完成事务操作。
数据不一致当协调者还没向各个参与者发送完Commit请求时自身发生崩溃,此时只有部分参与者接收到请求,而其他参与者没有收到,因此会出现数据不一致的现象。
太过保守二阶段提交协议没有设计较为完成的容错机制,任意一个节点的失败都会导致整个事务的失败。
3PC3PC (Three-Phase Commit),即三阶段提交,是2PC的改进版。
阶段一:CanCommit- 事务询问
协调者向所有的参与者发送一个包含事务内容的CanCommit请求,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
-
各参与者向协调者反馈事务询问的响应
参与者在接收到来自协调者的CanCommit请求后,正常情况下,如果其自身认为可以顺利执行事务,那么会反馈Yes响应,并进入预备状态,否则反馈No响应。
此时,协调者会根据各参与者的反馈情况来决定是否可以进行事务的PreCommit操作,有以下两种可能。
执行事务预提交 假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务预提交。
-
发送预提交请求
协调者向所有参与者发出preCommit请求,并进入Prepared阶段。
-
事务预提交
参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。
-
各参与者向协调者反馈事务执行的响应。
如果参与者成功执行事务操作,那么就会反馈给协调者Ack响应,同时等最终的指令:提交(commit)或中止(abort)。
假如其中任何一个参与者向协调者反馈了No响应,或者等待超时,那么就会中断事务。
-
发送中断请求
协调者向所有参与者发送 abort 请求。
-
中断事务
无论是收到来自协调者的abort请求,或者等待协调者请求过程中出现超时,参与者都会中断事务。
该阶段将进行真正的事务提交,有以下两种可能。
执行提交-
发送提交提交请求
进入这一阶段,它接收到了来自所有参与者的Ack响应,那么它将从"预提交"状态转换成"提交"状态,并向所有的参与者发送doCommit请求。
-
事务提交
参与者接收到doCommit请求后,会正式执行事务提交操作,并在完成提交之后释放事务资源。
-
反馈事务提交结果
参与者在完成事务提交后,向协调者发送Ack消息。
-
完成事务
协调者接收到所有参与者反馈的Ack消息后,完成事务。
进入这一阶段,并且任意一个参与者向协调者反馈了No响应,或者等待超时之后,那么就会中断事务。
-
发送中断事务
协调者向所有参与者发送abort请求。
-
事务回滚
参与者接收到abort请求,会利用阶段二的undo信息执行事务回滚,并释放资源。
-
反馈回滚结果
参与者完成事务回滚之后,向协调者发送Ack消息。
-
中断事务
协调者接收到所有参与者反馈的Ack消息后,中断事务。
优点:相比较二阶段提交协议,就是降低了参与者的阻塞范围,并且能够出现单点故障后继续达成一致。
缺点:在参与者接收到preCommit,如果出现了网络分区,协调者和参与者无法进行正常网络通信,这种情况下,参与者依然会进行事务提交,必然会出现数据不一致问题。
2.2 Paxos 算法这是一种基于消息传递且具有高度容错性的一致性算法,是目前公认的解决分布式一致性问题的最有效算法。
在常见的分布式系统中,总会发生诸如机器宕机或网络异常等情况。Paxos算法需要解决的问题是如何在异常的分布式系统中,快速且正确在集群内部对某个数据达成一致,并且保证不论发生以上异常都不会破坏整个系统的一致性。
为了保持Paxos算法流程的可持续性,以避免陷入"死循环",就必须选择一个主Proposer,并规定只有主Proposer才能提出议案,这样一来,只要主Proposer和过半的Acceptor能够正常网络通信,那么但凡主Proposer提出一个编号更大的提案被提出或正在接收批准。当然,如果Proposer发现当前算法流程中已经有一个编号更大的提案被提出或正在接受批准,那么它会丢弃当前这个编号的提案,并最终能够选出一个编号足够大的提案。因此,如果系统中有足够多的组件(包括Proposer、Acceptor和其他网络通信组件)能够正常工作,那么通过选择一个主Proposer,整套Paxos算法流程才能保持活性。
小结二阶段提交协议解决了分布式事务的原子性问题,保证了分布式事务的多个参与者要与都执行成功,要么都执行失败。但存在着同步阻塞、无限期等待和脑裂问题。
三阶段提交协议在二阶段协议的基础上,添加了PreCommit过程,从而避免了二阶段协议中的无限期等待问题。
而Paxos算法引入"过半"的理念,通俗地讲就是少数服从多数的原则,同时支持分布式节点角色之间的轮换,这极大避免分布式的单点问题,因此既解决了无限期等待问题,也解决了"脑裂"问题,是目前最优秀的分布式一致性协议之一。



