Paxos算法

PAXOS算法

paxos算法是基于消息传递且具有高度容错特性的一致性算法。是目前公认的解决分布式一致性问题最有效的算法之一。
Q:一致性算法是什么?
背景: 有一组可以提议的进程.
一致性算法: 确保这些被提议的值中有且只有一个被选中. (如果没有值被提出, 那么就没有值会被选中.) 如果一个值被选中, 那么每个进程必须要可以感知到.

问题产生的背景

在常见的分布式系统中,总会发生诸如机器宕机或网络异常(包括消息的延迟、丢失、重复、乱序,还有网络分区)等情况。Paxos算法需要解决的问题就是如何在一个可能发生上述异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,并且保证不论发生以上任何异常,都不会破坏整个系统的一致性。

相关概念

角色
现在通过上面的描述我们可以总结出来几个角色:
1) 提议者(proposer): 进行提议的角色
2) 批准者(acceptor): 通过提议的角色
3) 学习者(learner): 感知(learn)被选中的提议
在具体的实现中,一个进程可能同时充当多种角色。比如一个进程可能既是Proposer又是Acceptor又是Learner。
提案
还有一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里。
Proposer可以提出(propose)提案;Acceptor可以接受(accept)提案;如果某个提案被选定(chosen),那么该提案里的value就被选定了。
选定提案
在何种情况下不同的进程认为提案被选中了?
Proposer:只要Proposer发的提案被Acceptor接受,Proposer就认为该提案里的value被选定了。
Acceptor:只要Acceptor接受了某个提案,Acceptor就认为该提案里的value被选定了。
Learner:Acceptor告诉Learner哪个value被选定,Learner就认为那个value被选定。
问题描述
假设有一组可以提出提案的进程集合。一个一致性算法需要保证提出的这么多提案中,只有一个提案被选定。如果一个提案被选定,那么所有进程都应该能学习(learn)到这个被选定的提案的内容。

实现一致性算法

由问题描述可知:需要确保这些提案中有一个被选中, 那么也就意味着即使只有一个提案我们也要有提案被选中. 那么很自然地我们可以做出如下的约束来满足这个需要:
P1. 一个Acceptor必须批准它收到的第一个提案
P1解决了只有一个提议的时候保证有可以选中. 但是有多个提议被不同的提案提出的时候怎么办呢?这里就提出了一个大多数(majority)的概念, 具体来讲就是被超过一半的acceptor通过的提案可以被选中.
显然P1是无法保证总能有一个提议会被大多数acceptor通过. 那么我们就需要继续寻找一个约束条件来解决产生大多数的问题. 根据P1的约束, 我们知道每个acceptor都会批准它收到的第一个提案, 这就要求每个acceptor必须要可能批准多个提案. (因为每个提案到达acceptor的顺序是随机的, 如果提案数量>=2, 就可能无法形成多数派.)
OK, 现在每个acceptor都可以批准多个提案, 为了后续描述方便我们给每个提案一个全局唯一的编号, 这样提案就由编号和值共同构成(记住我们最终的目标是选出值): [m, v],再根据我们之前的要求: “只有一个值被选中”, 我们做出如下约束:
P2. 如果一个值为v的提案被选中, 那么更高编号的被选中的提案的值必须也为v
P2可以保证我们说的只有一个值被选中, 但是如何满足P2呢?我们可以让一个值v被选中之后, 那么后续所有的acceptor所能批准的更高版本的提案的值也必须是v:
P2a. 如果值为v的提案被选中, 那么后续任何acceptor能批准的更高版本的提案都必须要有值v.
P2a从acceptor方面入手,,可以确保P2成立。 我们说P1+P2a是可以保证一致性算法的安全性的,但是让我们考虑这种情况:
由于通讯是异步的, 一个提案[m, v]在已经被选定之后可能还有某个acceptor a还没有接收到任何提议, 这个时候如果另一个proposer起草了一个版本更高的proposal: [m+k, v’], 而且如果[m+k, v’]是a收到的第一个提议, 根据P1, a就必须通过它. 这样P2a就很难保证了.
根据上面的例子可以看出来, 由于P1的存在我们无法阻止acceptor批准它所收到的第一个proposal, 导致了P2a很难实现, 那怎么办? 我们可以看到如果上面的例子中v=v’的话, P2a还是可以成立的. 所以我们可以做一个更强的限定, 帮助我们使P2a成立:
P2b. 如果值为v的提案被选中, 那么后续任意的proposer所起草的更高编号的提案的值必须也是v.
P2b就很强了, 后续proposer起草的更高编号的提案的值都是v, 那么不管acceptor端怎么做, 肯定可以满足P2a了, 这个是不言而喻的. 那么我们现在要解决的问题就是如何使P2b成立.
假设我们有[M, V]被选中, 那么我们现在要证明的是对于N>M, [N, V’]可以被通过必须满足V=V’. 从P2b的描述上我们可以看出来它更像是一种递归的定义方式. 所以我们可以尝试用数学归纳法来证明P2b:
文中采用了第二数学归纳法:
1. 假设编号在 M..(N-1) 之间的提案的值都是V, 证明编号为N的值也为V
2. 因为M被选中, 所以必然存在一个超过半数的(majority)acceptor的集合C, C中的每个acceptor都批准了该提案.
3. 那么显然由1,2我们可以得出C中的每个acceptor都批准了M..N-1之间的某个提案, 且这个被批准的提案值为V.
因为C是majority, 所以它和另外任意一个majority S一定会有一个非空的交集. 那么我们可以知道, 对于任意一个majority S, 它里面肯定存在acceptor批准了M..N-1之间的某个提案, 且这个被批准的提案值为V.
据此我们可以得出让P2b满足的条件:
P2c. 对于任意的N和V, 如果[N, V]被提出, 那么肯定存在一个由半数以上(majority)的acceptor组织的集合S, 满足下面两个条件之一
(a) S中不存在任何批准过编号小于N的提案的Acceptor
(b) S中所有Acceptor批准的编号小于N的提案中编号最大的值为V
这里的可以看到(b)就是我们上面推导出来的那个 (对于任意一个majority S, 它里面肯定存在acceptor批准了M..N-1之间的某个提案, 且这个被批准的提案值为V.), 那么对于(a)怎么理解? 实际上我们推导了半天都是基于P2b的”如果值为v的提案被选中”, 那如果没有编号小于N的提案被选中就是(a) 的情况。
总结:满足p1&P2c我们就能够确保一致性算法的安全性。

Learning选中的值

当有提案被选中之后 Learning就比较简单了,有以下几种方案。
learning

Paxos

Paxos实现只需要满足我们上面推出的P1+P2c就可以了
如何保证P2c成立
要维护P2c的成立, 一个proposer在起草提案[n, x]之前必须要先知道 (某个majority中) 各个acceptor目前通过的小于n最高的提案. 这很容易, 但是这个可能是变化的, 如何预测将来就比较困难了. 和上面P2a到P2b的思路类似, 相较于直接预测将来, proposer通过向acceptor们索取承诺来解决这个问题. 换句话说, proposer请求acceptor们不要再通过任何低于n的提案了.
于是我们有了下面的起草提案的算法:
proposer选择一个新的编号n, 并发送给 (某个majority中) 每个acceptor, 要它做出如下回应:
(a) 承诺不会再通过任何比n小的提案
(b) 小于n的最大编号的提案(如有)
如果proposer受到了绝大多数acceptor的响应, 那么它就可以起草一个提案. 提案的编号是n, 值是根据 1 中的 (b) 里面响应的提案的值来的(如果没有提案, 或者提案值为空, 那么这个proposer可以用任意值)
上面提到的proposer向acceptor发起的请求我们称之为prepare request.
当proposer经历了上面过程, 并起草了提案之后, 它就可以向 (某个majority中) acceptor们发送这个提案并等待它们审批. (注: 并不一定是上面prepare request发给的那个majority集合.) 这个请求被称为accept request.
如何保证P1成立
1. acceptor可以在任意时刻响应prepare request;
2. acceptor可以在不违背响应prepare request的前提下, 响应(通过)任何accept request
所以对于acceptor来说可以概括为:
P1a. 一个acceptor可以通过一个proposal [n, v], 当且仅当它没有响应过任何编号大于n的prepare request.
很明显P1a => P1
所以Paxos可以保证P2c & P1, 这样我们就得到了一个一致性的算法!

优化

这里的优化是通过确保上述步骤正确的情况下尽可能忽略prepare request. 就是当acceptor已经通过了一个编号为n的proposal, 那么很明显它不需要再响应任何编号小于n的prepare request.

这样做, 每个acceptor只需要记住它已经批准的提案的最大编号和它已经响应的prepare request提案的最大编号以便在故障或者重启的情况下可以正确恢复. 而对于proposer而言, 只要它可以保证不会产生具有相同编号的提案那么就可以丢弃任意的提案以及它所有的运行时的状态信息.

Paxos运行过程图解

Paxos运行过程

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值