一致性协议
2PC
2PC即二阶段提交,是计算机网络尤其是在数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。
协议说明:二阶段提交协议是将事务的提交过程分成两个阶段来进行处理。
阶段一:提交事务请求
投票阶段
阶段二:执行事务提交
执行阶段
优缺点
优点:原理简单,实现方便
缺点:同步阻塞、单点问题、脑裂、太过保守
同步阻塞
在二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态
单点问题
协调者的角色在整个二阶段提交协议中起到了非常重要的作用,是单点的。
数据不一致
在二阶段提交协议的阶段二,即执行事务提交的时候,commit请求并未发送到所有的参与者。
太过保守
如果在协调者指示参与者进行事务提交询问的过程中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息的换,这时协调者只能依靠自身的超时机制来判断是否需要中断事务,这样的策略显得比较保守。换句话说,二阶段提交协议没有涉及较为完善的容错机制,任意一个节点的失败都会导致整个事务的失败。
3PC
三阶段提交是2PC的改进版,将二阶段提交协议的“提交事务请求”过程一分为二,形成了由CanCommit,PreCommit和doCommit三个阶段组成的事务处理协议。
阶段一:CanCommit
- 事务询问
- 各参与者向协调者反馈事务询问的响应
阶段二:PreCommit,两种情况
执行事务预提交:协调者从所有的参与者获得的反馈都是yes响应,那么就会执行事务预提交。
- 发送预提交请求
- 事务预提交
- 各参与者向协调者反馈事务执行的响应
中断事务:假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈响应,那么就会中断事务
- 发送中断请求
- 中断事务
阶段三:doCommit,两种情况
执行提交:
- 发送提交请求
- 事务提交
- 反馈事务提交结果
- 完成事务
中断事务
- 发送中断请求
- 事务回滚
- 反馈事务回滚结果
- 中断事务
需要注意,一旦进入阶段三,可能会存在以下两种故障。
- 协调者出现问题
- 协调者和参与者之间的网络出现故障
无论出现那种情况,最终都会导致参与者无法及时接受到来自协调者的doCommit或者abort请求,针对这样的异常情况,参与者都会在等待超时之后,继续进行事务提交。
优缺点
优点:相较于2PC,3PC最大的有点就是降低了参与者的阻塞范围,并且能够在单点故障后继续达成一致。
缺点:容易出现数据不一致性
Paxos
分布式一致性协议是一种基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。
Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致性,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。
问题描述
假设有一组可以提出提案的进程集合,那么对于一个一致性算法来说需要保证以下几点:
- 在这些被提出的提案中,只有一个会被选定
- 如果没有填被提出,那么就不会有被选定的提案
- 当一个提案被选定后,进程应该可以获取被选定的提案信息
对于一致性来说,安全性需求如下:
- 只有被提出的提案才能被选定
- 只能有一个值被选定
- 如果某个进程认为某个提案被选定了,那么这个提案必须是真的被选定的那个
从整体来说,Paxos算法的目标就是要保证最终有一个提案会被选定,当提案被选定后,进程最终也能获取到被选定的提案。
有三种参与角色,我们用Proposer,Acceptor和Learner来表示
假设不同参与者之间可以通过收发消息来进行通信,那么:
- 每个参与者以任意的速度执行,可能会因为出错而停止,也可能会重启。同时,即使一个提案被选定后,所有的参与者也都有可能失败或重启,因此除非那些失败或重启的参与者可以记录某些信息,否则将无法确定最终的值。
- 消息在传输过程中可能会出现不可预知的延迟,也可能会重复或丢失,但是消息不会损坏,即消息内容不会被篡改
推到过程
P1:一个Acceptor必须批准它收到的第一个提案。
因为以上两种情况,在P1的基础上,再加上一个提案
被选定需要由半数以上的Acceptor批准的需求暗示着一个Acceptor必须能够批准不止一个提案。
我们使用一个全局的编号来唯一标识每一个被Acceptor批准的提案,当一个具有某Value值的提案被半数以上的Acceptor批准后,我们就认为该Value被选定了,此时我们也认为该提案被选定了。
P2:如果编号为M0、Value值为V0的提案被选定了,那么所有比编号M0更高的,且被选定的提案,其Value值必须也是V0.
一个提案要被选定,其首先必须被至少一个Acceptor批准,因此我们可以通过满足如下条件来满足P2。
P2a:如果编号为M0、Value值为V0的提案被选定了,那么所有比编号M0更高的,且被Acceptor批准的提案,其Value值必须也是V0。
P2b:如果一个提案【M0,V0】被选定后,那么之后任何Proposer产生的编号更高的提案,其Value值都为V0。
因为一个提案必须在被Proposer提出后才能被Acceptor批准,因此P2b包含了P2a,进而包含了P2。
论证P2b成立。
P2c:对于任意的Mn和Vn,如果提案【Mn,Vn】被提出,那么肯定存在一个由半数以上的Acceptor组成的集合S,满足一下两个条件中的任意一个。
- S中不存在任何批准过编号小于Mn的提案,其中编号最大的那个提案其Value值是Vn。
Proposer生成天
Proposer选择一个新的提案编号Mn,然后向某个Acceptor集合的成员发送请求,要求该集合中的Acceptor做出如下回应。
- 向Proposer承诺,保证不再批准任何编号小于Mn的提案
- 如果Acceptor已经批准过任何提案,那么其就向Proposer反馈当前该Acceptor已经批准的编号小于Mn但为最大编号的哪个提案的值。
Acceptor批准提案
- Prepare请求:Acceptor可以在任何时候响应一个Prepare请求
- Accept请求:在不违背Accept现有承诺的前提下,可以任意响应Accept请求。
算法优化
尽可能地武略Prepare请求
算法陈述
阶段一
- Proposer选择一个提案编号Mn,然后向Acceptor的某个超过半数的子集成员发送编号为Mn的Prepare请求。
- 如果一个Acceptor收到一个编号为Mn的Prepare请求,且编号Mn大于该Acceptor已经响应的所有Prepare请求的编号,那么它就会将它已经批准过的最大编号的提案作为响应反馈给Propser,同时该Acceptor会承诺不会在批准任何编号小于Mn的提案。
阶段二
- 如果Proposer收到来自半数以上的Acceptor对于其发出的编号Mn的Prepare请求的响应,那么它就会发送一个针对[Mn,Vn]提案的Accept请求给Acceptor。
- 如果Acceptor收到这个针对[Mn,Vn]提案的Accept请求,只要该Acceptor尚未对编号大于Mn的Prepare请求做出响应,它就可以通过这个提案。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。