非阻塞复制?
- 假设使用主备复制
- 如何判断主服务器是故障还是仅仅响应慢?
- 如果主服务器仅仅响应慢,可能最终会有两个主服务器!
- 依赖视图服务器来决定?
- 如果视图服务器宕机怎么办?复制?
- 如何复制视图服务器?主备复制?
- ……
我们需要 分布式共识
FLP:共识的不可能性
- 在一个异步分布式系统中,一个确定性协议保证在有界时间内达成共识是不可能的(即使只有一个故障进程)
- 如果感兴趣,请阅读论文
- 我们应该怎么做?
- Paxos:只要大多数参与者存活,且有足够长的无进一步故障的时间段,就可以非阻塞地工作
原始的Paxos论文
- 兼职议会
- 议会通过通过一系列编号的法令来确定法律
- 立法者可以随意进出议会厅
- 没有中央记录批准的法令
- 相反,每个立法者携带一个账本
今天:简化版Paxos
- 一组可以提出值的进程
- 进程可以崩溃并恢复
- 通过消息进行异步通信
- 消息可能需要任意长的时间才能送达
- 消息可能会丢失和重复,但不会被篡改
- 目标:对单一值达成共识
思想实验
- 一群朋友决定去哪里吃午餐
- 任何人随时可以提议一个餐馆
- 点对点的、不可靠的消息
- 有些朋友可能在任何时候都离线
Paxos中的3种角色
提议者
- 提出要选择的值(提案)
接受者
- 接受/拒绝提案
- 集体决定何时选择一个值
学习者
- 一旦选择了一个值,就学习决定的值
所有逻辑角色
- 多个角色可以共存于同一个物理节点上
游戏:共识
安全性
- 只有被提议过的值可以被选择
- 只选择一个值
- 除非一个值被确定选择,否则进程永远不会知道该值已经被选择
活性
- 最终会选择某个提议的值
- 如果一个值被选择,进程最终会得知
术语
- 值:要达成共识的可能的值/操作
- 提议:选择一个值;提议有唯一编号
- 接受:特定提议/值的接受
- 选择:被大多数接受的提议/值
- 学习:提议被选择的事实已知
为什么要多数派?
- 多数派:超过一半的参与者
- 多数派相交:对于任意两个多数派S和S',都有一些节点同时在S和S'中
我们的方法
从共识的广义定义开始
- 我们最终应该选择一个值
- 我们应该只选择一个值
将定义细化/缩小到我们可以实现的东西
选择一个值:简单解决方案
使用单个接受者
如果接受者失败了怎么办?
- 仅在“足够大”的接受者集合接受时选择
- 使用多数派集合保证最多只有一个值被选择
接受一个值
- 假设只有一个值由单一提议者提议。
- 那个值应该被选择!
- 第一个要求:
P1: 一个接受者必须接受它收到的第一个提议
- ...但如果我们有多个提议者,每个提议者提出不同的值怎么办?
P1 + 多个提议者
没有值被选择
接受者应该接受多个提议
处理多个提议
接受者必须(能够)接受不止一个提议
为了跟踪不同的提议,为每个提议分配一个自然数
- 一个提议然后是一对(psn, 值)
- 不同的提议有不同的psn
- 当一个提议被大多数接受者接受时,该提议被选择
- 当一个提议的值被选择时,一个值被选择
分配提议编号
- 提议编号必须是唯一且无限的
- 提议编号服务器不行...
- 相反,为每个提议者分配一个无限的切片
- 提议者i(共N个)获得:i, i+N, i+2N, i+3N, …
回到这个问题: 如何确保只选择一个值
选择一个唯一的值
- 我们需要确保所有被选择的提议都导致选择同一个值
- 我们引入第二个要求(通过对提议编号进行归纳)
P2. 如果一个值为v的提议被选择,那么每一个编号更高的被选择的提议都有值v
如何实现P2?
P2. 如果一个值为v的提议被选择,那么每一个编号更高的被选择的提议都有值v
可以通过以下方式满足:
P2a. 如果一个值为v的提议被选择,那么任何接受者接受的每一个编号更高的提议都有值v
那么P1呢?
它如何知道不接受?
我们还需要P1吗?
- 是的,以确保某个提议被接受
P1和P2a如何共存?
- 异步是一个问题...
P2的另一种解释
P2a. 如果一个值为v的提议被选择,那么任何接受者接受的每一个编号更高的提议都有值v
我们加强为:
P2b: 如果一个值为v的提议被选择,那么任何提议者发起的每一个编号更高的提议都有值v
实现P2
P2b: 如果一个值为v的提议被选择,那么任何提议者发起的每一个编号更高的提议都有值v
假设一个提议者p想要发起一个编号为n的提议。p应该提议什么值?
两种情况:
- (n' , v) 一个编号为n',值为v的提议被选择,且n' < n
- 没有这样的提议被选择
Q应该提议什么值?
Q如何知道一个值已经被选择?
Q如何知道没有值被选择?
实现P2(I)
P2b: 如果一个值为v的提议被选择,那么任何提议者发起的每一个编号更高的提议都有值v
假设一个提议者p想要发起一个编号为n的提议。p应该提议什么值?
- 如果(n',v)被选择,且n' < n,那么在每一个多数派集合S的接受者中至少有一个接受者接受了(n',v)...
- ...所以,如果存在一个多数派集合S,其中没有接受者接受(或将接受)编号小于n的提议,那么p可以提议任何值
实现P2(II)
P2b: 如果一个值为v的提议被选择,那么任何提议者发起的每一个编号更高的提议都有值v
通过执行以下不变性来实现
P2c: 对于任何v和n,如果发出了一个值为v且编号为n的提议,则存在一个由多数接受者组成的集合S,使得:
- 集合S中的没有接受者接受了编号小于n的任何提议,或者
- v是S中接受者接受的所有编号小于n的提议中编号最高的提议的值
实现P2c
我们对第三个接受者知道什么?
它能接受(1,A)吗?No。
它能接受(2,K)吗?Yes。
我们需要咨询多少节点?
咨询全部3个?
如果大多数节点正常工作,我们希望实现非阻塞
咨询1和2?安全地提出(4,K)
咨询1和3?安全地提出(4,A)
咨询2和3?安全地提出(4,K)
预测未来?
- 为了维护P2c,一个希望提出编号为n的提议的提议者必须了解在某些大多数接受者中,每个接受者已经或将会接受的编号小于n的最高编号提议(如果有的话)
- 通过从大多数接受者那里获取一个承诺来避免预测未来,该承诺是之后不再接受任何编号小于n的提议
两种类型的消息:准备和接受
![](https://i-blog.csdnimg.cn/blog_migrate/f94d0c0607b2e999a60343fe36b7c3ee.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0a287fd3f09e3dda99622a8ac9cc1e8d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e3fbc2a491cbddebfeedee778ad19160.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c15fc09ae462ea955101774b8dd333b7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0c2b9f1837acf21a2c654213f7e5ae02.png)
选择一个值的整合 阶段1
- 提议者选择一个新的n并向大多数接受者发送<准备,n>
- 如果接受者a接收到<准备,n’>,其中n’ > n对于它已经响应的任何<准备,n>,那么它对<准备, n’>做出响应
- 承诺不再接受任何编号小于n’的提议
- 它已经接受的最高编号提议(如果有的话)
选择一个值的整合 阶段2
- 如果提议者从大多数接受者那里收到对<准备,n>的响应,那么它向每个人发送<接受,n,v>,其中v是
- 响应中最高编号提议的值
- 如果响应没有报告任何提议,则为任何值
- 如果接受者接收到<接受,n,v>,除非它在此期间已经对<准备,n’>做出了响应,其中n’ > n,否则它接受该提议
了解选择的值(I)
- 一旦一个值被选择,学习者应该得知它。可能有许多策略:
- 每个接受者每次接受一个提议时就通知每个学习者。
- 接受者通知一个特定的学习者,然后由他通知其他学习者。
了解选择的值(II)
- 由于故障(消息丢失和接受者崩溃),学习者可能无法得知一个值已经被选择
FLP怎么样?
活性
选举一个特定的提议者
- 进度不是保证的:
回到状态机复制
问题和疑问
- 每个操作需要两轮通信
- 对哪个实例提出操作提议?
- 日志中的空隙?
- 如何选举特定提议者?
一种解决方案:PMMC
Paxos变得适度复杂
高层思想:
- 领导者通过对所有实例运行Paxos阶段1来选举自己
- 一旦被选举,只对每个提议运行Paxos阶段2
- 如果领导者死亡,其他节点重复这个过程(自我选举,等等)
- Paxos确保安全性
阅读PMMC论文!