Paxos 学习笔记1
Posted 路过的摸鱼侠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Paxos 学习笔记1相关的知识,希望对你有一定的参考价值。
Paxos 学习笔记1 - Basic Paxos
图片来自 John Ousterhout 的 Raft user study 系列课程
共识问题是在复制状态机的背景下被提出的
复制状态机
复制状态机是指一组状态机相同的节点,只要它们接收到的指令顺序相同,那么就会表现出相同的行为,并产生相同的结果,因此理想的情况下,即使有些机器崩溃,剩下的机器也能提供服务(只要大多数服务器还活着),服务器集群形成一个高可用的状态机
复制状态机在分布式系统中被用于解决很多容错的问题
- 例如,大规模的系统中通常都有一个集群领导人
- 像 GFS、HDFS 和 RAMCloud
- 典型应用就是用独立的复制状态机管理领导选举、存储配置信息并在领导人宕机的情况下保证集群存活
- 比如 Chubby 和 ZooKeeper
复制状态机的实现手段:replicated log
- 为了实现复制状态机,集群不仅要对需要执行的单条指令达成共识,还要对指令的执行顺序达成共识
- 由共识模块来保证,这也就是我们要使用到 Paxos 等共识算法的地方
- replicated log 是一种先写日志(Write-Ahead Log),每条日志项都是状态机要执行的指令
- 节点会按日志中的指令顺序去执行指令,由于集群对 replicated log 中日志的顺序达成了共识,因此确保了所有的节点共享相同的状态
模型
Paxos 中有三种角色
- 提议者(proposer)
- 主动的:提议值供大家选择
- 处理客户端请求
- 接受者(acceptor)
- 被动的:回复提议者的消息,即投票
- 接受不代表被选中,只有多数接受者接受了某个值,这个值才是被选中了
- 存储被选中的值
- 存储决策的过程
- 被动的:回复提议者的消息,即投票
- 学习者( learner)
- 想要知道哪个值被选中了
- 一开始只有提议者知道被选中的值
- 提议者必须通过某种方式使得学习者也知道
- 想要知道哪个值被选中了
单个进程可以担任多个角色
Paxos 采用异步网络下的 fail-stop 故障模型(非拜占庭故障)
- 角色的处理速度未知,可能故障,可能重启,因此必须将已经选中的值持久化
- 但只要服务器正常运作,它们的行为就是正确的
- 与之相反是拜占庭故障,可以存在恶意节点以未知的方式运作
- 消息的传递速度未知,可能重复,可能丢失,但消息不会被破坏
Paxos 算法由两部分组成
- Basic Paxos
- 只考虑在共识中就一个值达成一致
- Multi-Paxos
- 将多个 Basic Paxos 实例结合起来就一组值达成共识
- 实现 replicated log 必须使用到 Multi-Paxos
Basic Paxos
Basic Paxos 解决的问题
一系列进程都可以提议(propose)值,共识算法要确保
- 这些值中的一个被选中
- 如果没有值被提出,那么不应该有值被选中
- 进程可以学习到已经被选中的值
共识问题的要求
- 安全性(safety)
- 选中的值必须是被提议的
- 只有一个值被选中
- 进程不会学习到没有被选中的值
- 活性(liveness)
- 某些被提议的值最终会被选中,且进程最终能学习到被选中的值
- 必须在有限时间内做出决议
单个接受者
最简单的场景是多个提议者、单个接受者,接受者接受第一个发给它的值,作为被选中的值,问题是如果接受者故障,整个系统就会不可用
多个接受者
采用多个接受者,用 quorum 的方式,即少数服从多数,决定被选中的值
如果接受者接受发给他的第一个值
最后可能没有一个值能取得多数的投票,这也就意味着我们无法保证在一轮投票中达成共识
如果接受者接受发给他的每个值
可能会有多个值被选中,违反了安全性要求
解决方案:
- 一旦一个值被选中,后续的提议必须提出同一个值
- 二阶段协议
- 也就是说 S5 提出提议前,必须看看有没有值已经被选中了,如果有,他就必须放弃自己的提议,提出已经被选中的值 red
二阶段协议
单纯的二阶段协议
单纯使用二阶段协议仍然无法解决这个问题,下图里 S1 和 S5 在第一个阶段都发现没有其他的值被选中,因此提出自己的提议,但在这个时序下会有两个不同的值被选中
解决方案:必须对提议做排序,旧的提议应该被拒绝
- 比如图中 S3 应该拒绝掉 S1 的提议
提议编号
给提议排序的手段是给每个提议加一个独一无二的编号,编号大的提议优先级高
最简单的做法就是用一个自增的整数+服务器 ID 作为编号,这个自增整数的最大值应该被持久化,防止服务器崩溃重启后复用已经使用过的编号
Basic Paxos 中使用的二阶段协议
- Prepare 阶段——提议者广播 Prepare RPC
- 看看有没有已经被选中的值,如果有,提议者的提议就应该使用这个值
- 阻止那些更老的还未完成的提议被选中
- Accept 阶段——提议者广播 Accept RPC
- 让接受者接受某个值
Prepare 阶段具体流程
提议者
为自己的提议选择一个提议编号 n,然后将该编号广播给接受者
接受者
- 如果接受者发现 n > minProposal
- minProposal 是该接受者会接受的最小提议编号
- 将 minProposal 更新为 n,这意味着两种承诺
- 再也不会接受提议编号小于等于 n 的 Prepare 提议
- 再也不会接受提议编号小于 n 的 Accept 提议
- 回复给提议者当前已经接受的提议编号和值(acceptedPropsal 和 acceptedValue),如果当前没有接受任何提议,那么提议值为空
提议者
- 当提议者收到多数接受者的回复
- 用这些回复里提议编号最大的提议值作为自己的提议值
- 如果所有回复的值都是空,提议者就可以使用自己的提议值
Accept 阶段具体流程
提议者
提议者广播提议编号和值(n 和 value)给接受者
接受者
- 如果接受者发现 n >= minProposal,接受该提议
- 更新 acceptedPropsal = minProposal = n
- 更新 acceptedValue = value
- 回复给提议者 minProposal
提议者
- 当提议者收到多数接受者的回复
- 如果有任何接受者拒绝了提议
- 也就是他回复的编号比提议者提出的提议编号大
- 说明提议在该轮没有被选中
- 提议者应当重新选择一个更大的提议编号,回到 Prepare 阶段
- 如果没有任何接受者拒绝该提议,说明该提议值被选中
- 只有提议者知道这个值被选中了
- 如果其他提议者想知道,必须发起他们自己的提议
- 如果有任何接受者拒绝了提议
以上是关于Paxos 学习笔记1的主要内容,如果未能解决你的问题,请参考以下文章