一、Paxos
协议
拜占庭将军问题
描述
一组拜占庭将军分别各率领一支军队共同围困一座城市。
为了简化模型,将各支军队的行动策略限定为进攻或撤离两种。因为部分军队进攻部分军队撤离可能会造成灾难性后果,因此各位将军必须通过投票来达成一致策略,即所有军队一起进攻或所有军队一起撤离。
同时各位将军分处城市不同方向,他们只能通过信使互相联系。在投票过程中每位将军都将自己投票给进攻还是撤退的信息通过信使分别通知其他所有将军,这样一来每位将军根据自己的投票和其他所有将军送来的信息就可以知道共同的投票结果而决定行动策略。
前提
在拜占庭将军问题中,默认是认为信使是不会被截获并且消息会传递到的。更多的情况中,将军中可能会出现叛徒、信使会被截获冒充、消息无法到达。而叛徒或信使冒充会恶意地向其他将军投票,给不同将军展示不同的投票结果,从而破坏了将军们执行的一致性。而此类错误则称为拜占庭错误。
如果系统能处理拜占庭将军错误正常运行的话,则称系统拥有拜占庭容错「Byzantine fault tolerance」,简称为BFT。
概述
介绍
Paxos
算法是 基于消息传递 且具有 高效容错特性 的一致性算法,目前公认的解决 分布式一致性问题 最有效的算法之一.
作用
在常见的 分布式系统 中,总会发生 节点宕机 或 网络异常 (包括消息的 重复、丢失、延迟、乱序、网络分区) 等情况。如果没有 Paxos
,那后续的 Raft
、ZAB
等算法就不会出现。
Paxos
算法主要就是解决如何在一个 发生如上故障 的分布式系统中,快速正确的在集群内 对某个值达成一致,并且保证 整个系统的一致性。
算法详解
节点描述
Paxos
算法将分布式系统中的节点分为三类:
- 提案节点
Proposer
:提出对某个值进行设置操作的节点,设置值这个行为就被称之为 提案 (Proposal
),值一旦设置成功,就是不会丢失也不可变的; - 决策节点
Acceptor
:是应答提案的节点,决定该提案是否可被投票、是否可被接受。提案一旦得到过半数决策节点的接受,即称该提案被 批准(Accept
),提案被批准即意味着该值不能再被更改,也不会丢失,且最终所有节点都会接受该它; - 记录节点
Learner
:不参与提案,也不参与决策,只是单纯地从提案、决策节点中学习已经达成共识的提案,譬如少数派节点从网络分区中恢复时,将会进入这种状态;
使用 Paxos
算法的分布式系统里的,所有的节点都是平等的,它们都可以承担以上某一种或者多种的角色,不过为了便于确保有明确的多数派,决策节点的数量应该被设定为奇数个,且在系统初始化时,网络中每个节点都知道整个网络所有决策节点的数量、地址等信息。
Prepare
阶段
Paxos
算法包括两个阶段,其中,第一阶段 Prepare
相当于抢占锁的过程。如果某个提案节点准备发起提案,必须先向所有的决策节点广播一个许可申请,即 Prepare
请求。提案节点的 Prepare
请求中会附带一个全局唯一的数字 n
作为提案 ID
,决策节点收到后,将会给予提案节点两个承诺与一个应答。
两个承诺
- 承诺不会再接受提案
ID
小于或等于n
的Prepare
请求; - 承诺不会再接受提案
ID
小于n
的Accept
请求;
一个应答
不违背以前作出的承诺的前提下,决策节点回复已经批准过的提案中 ID
最大的那个提案所设定的值和提案 ID
,如果该值从来没有被任何提案设定过,则返回空值。
如果违反此前做出的承诺,即决策节点收到的提案 ID
并不是决策节点收到过的最大的,那就直接对此 Prepare
请求不予理会。
为何需要两个承诺和一个应答?
需要两个承诺是因为防止滞留在网络中的重复提案被决策节点重复执行。
Accept
阶段
当提案节点收到了多数派决策节点的应答,即 Promise
应答后,可以开始第二阶段 Accept
过程。
提案节点会收到两种结果
- 如果提案节点发现所有响应的决策节点此前都没有批准过该值,即响应为空,那说明它是第一个设置值的节点,可以随意地决定要设定的值,将自己选定的值与提案
ID
,构成一个二元组“(id, value)
”,再次广播给全部的决策节点 (Accept
请求); - 如果提案节点发现响应的决策节点中,已经有至少一个节点的应答中包含有值了,那它就不能够随意取值了,必须无条件地从应答中找出提案
ID
最大的那个值并接受,构成一个二元组“(id, maxAcceptValue)
”,再次广播给全部的决策节点 (Accept
请求);
当每一个决策节点收到 Accept
请求时,都会在不违背以前作出的承诺的前提下,接收并持久化对当前提案 ID
和提案附带的值。如果违反此前做出的承诺,即收到的提案 ID
并不是决策节点收到过的 最大 的,那允许直接对此 Accept
请求不予理会。
当提案节点收到了多数派(超过半数)决策节点的应答 Accepted
请求后,协商结束,共识决议形成,将形成的决议发送给所有记录节点进行学习。
如果提案节点发现响应的决策节点中,已经有至少一个节点的应答中包含有值了,那它就不能够随意取值了,必须无条件地从应答中找出提案 ID 最大的那个值并接受? 有了这个前提,一个值设置完成后,不是无法改变了吗?
其实这个疑问是对整个决策的生命周期存在的误解。协商结束,提案节点形成决议才是真正的流程结束,前边所有的过程都是在一个生命周期单元之内完成的。生命周期内,值一旦设置成功,就是不会丢失也不可变的。
一个周期包括 Prepare
和 Accept
两个阶段,不同周期之间互不影响,即==某个值在不同周期里是不会在 Prepare
做出有值的响应的==。
存在的问题
Basic Paxos
的价值在于开拓了分布式共识算法的发展思路,但它因有如下缺陷,一般不会直接用于实践:
Basic Paxos
只能对单个值形成决议,并且决议的形成至少需要两次网络请求和应答,高并发情况下将产生较大的网络开销;- 多个提案节点存在的情况下,分别对决策进行一来一往版本越来越高的
Prepare
请求,导致Accept
阶段一直失败。极端情况下甚至可能形成活锁;- 由于多个
Proposer
互相抬高编号导致双方一直Accept
阶段失败;
- 由于多个
Paxos
协议一定保证节点数据是一致的吗?
会,因为在 Accept
阶段,只要提案节点收到超过半数的返回接受,那么提案节点就认为本次协商结束。
所以,还是可能会出现从不同节点同个数据存在不同结果的情况。
Paxos
协议既然会有节点数据不一致的情况,那读取的时候会有问题吗?
如果 Paxos
协议确定一个值之后,需要用相同的方法把这个值读出来,即请求所有的节点该值,然后发现某个值占多数,最终读出来的值就是这个值。
如果能保证一致,那么读的效率会提升非常多,这就是 raft
协议了。类似于 Proposer
完成 Accept
请求之后,会向所有的决策节点再发送一个 commit
请求,表示这个提议已经被接受了,如果不是这个提议的就赶紧修改过来。当然这只是 raft
协议相对 Paxos
的一个优化,raft
协议还对 Paxos
协议的其他地方做了优化,让其更加高效。
二、Multi Paxos
协议
Basic Paxos
存在的问题
Basic Paxos
的活锁问题,两个提案节点互不相让地争相提出自己的提案,抢占同一个值的修改权限,导致整个系统在持续性地“反复横跳”,外部看起来就像被锁住了一样。这个问题 源于任何一个提案节点都能够完全平等地、与其他节点并发地提出提案而带来的复杂问题。
Multi Paxos
Multi Paxos 对 Basic Paxos 的核心改进是增加了“选主”的过程,提案节点会通过定时轮询,确定当前网络中的所有节点里是否存在有一个主提案节点,一旦没有发现主节点存在,节点就会在心跳超时后使用 Basic Paxos
中定义的准备、批准的两轮网络交互过程,向所有其他节点广播自己希望竞选主节点的请求,希望整个分布式系统对“由我作为主节点”这件事情协商达成一致共识,如果得到了决策节点中多数派的批准,便宣告竞选成功。
选主完成之后,除非主节点失联之后发起重新竞选,否则从此往后,就只有主节点本身才能够提出提案。此时,无论哪个提案节点接收到客户端的操作请求,都会将请求**转发给主节点来完成提案,而主节点提案的时候,也就无需再次经过准备过程,因为可以视作是经过选举时的那一次准备之后,后续的提案都是对相同提案 ID
的一连串的批准过程**。
协议流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SST1Kd9i-1660056210672)(D:\note_image\1efea29e923b446e860302aa03217573_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.png)]
这时候的二元组 (id, value)
已经变成了三元组 (id, i, value)
,这是因为**需要给主节点增加一个“任期编号”,这个编号必须是严格单调递增的**,以应付主节点陷入网络分区后重新恢复,但另外一部分节点仍然有多数派,且已经完成了重新选主的情况,此时 必须以任期编号大的主节点为准。
当节点有了选主机制的支持,在整体来看,就可以进一步简化节点角色,不去区分提案、决策和记录节点了,统统以“节点”来代替,节点只有主 Leader
和从 Follower
的区别,此时协商共识的时序图如图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xUSp93T-1660056210673)(D:\note_image\d5d6570ca78d4e039f0091c2c10745b1_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.png)]