Paxos协议是什么?
- 一个可靠的存储系统:基于多数派读写
- 每个paxos实例用来存储一个值
- 用2轮RPC(远程调用)来确定一个值
- 一个值“确定”后不能被修改
- “确定”指被多数派接受写入
- 强一致性
Paxos的目的:
目的是为了解决分布式环境下一致性的问题。
多个节点并发操纵数据,如何保证在读写过程中数据的一致性,并且解决方案要能适应分布式环境下的不可靠性
Paxos概念:
Proposer:发起paxos的进程
Acceptor:存储节点,接受、处理和存储消息
Quorum(Acceptor的多数派):n/2+1个Acceptor
Round:一轮包含两个阶段:Phase-1 & Phase-2
每一轮的编号(rnd):单调递增;后写胜出;全局唯一(区分Proposer)
Acceptor看到的最大rnd(last_rnd):Acceptor记住这个值来识别哪个proposer可以写
Value(v):Acceptor接受的值
Value round number(vrnd):Acceptor接受的v的时候的rnd
值‘被确定的’含义:有多于半数个Acceptor接受了这个值
Learner:
- Acceptor发送phase-3 到所有learner角色,让learner知道一个值被确定了
- 多数场合Proposer就是1个Learner
Livelock:
多个Proposer并发对1个值运行paxos的时候,可能会相互覆盖对方的rnd,然后提升自己的rnd再次尝试,然后再次产生冲突,一直无法完成
A Round:
当Acceptor收到 phase-1的请求时:
- 如果请求中 rnd 比Acceptor的 last_rnd小,则拒绝请求
- 将请求中 rnd 保存到本地的 last_rnd(这个Acceptor只接受带有last_rnd的 phase-2请求)
- 返回应答,带上自己之前的 last_rnd 和之前已接收的 v
当Proposer收到Acceptor发回的应答:
- 如果应答中 last_rnd大于发出的 rnd:退出
- 从所有应答中选择 vrnd 最大的 v:不能改变(肯可能)已经确定的值
- 若所有应答的 v 都是空,可以选择自己要写入v
- 如果应答不够多数派,退出
Proposer:
发送phase-2,带上 rnd 和上一步决定的 v
Acceptor:
- 拒绝 rnd ≠Acceptor的last_rnd 的请求
- 将phase-2请求中的v写入本地, 记住v为‘已接收的值’
- last_rnd == rnd保证没有其他proposer在此过程中写入过其他值
在搜集阅读的过程中,发现了一个很有趣生动的实例,帮助更好理解paxos协议:
原文链接:https://blog.csdn.net/cnh294141800/article/details/53768464
具体实例:
假设的3军问题
1) 1支红军在山谷里扎营,在周围的山坡上驻扎着3支蓝军;
2) 红军比任意1支蓝军都要强大;如果1支蓝军单独作战,红军胜;如果2支或以上蓝军同时进攻,蓝军胜;
3) 三支蓝军需要同步他们的进攻时间;但他们惟一的通信媒介是派通信兵步行进入山谷,在那里他们可能被俘虏,从而将信息丢失;或者为了避免被俘虏,可能在山谷停留很长时间;
4) 每支军队有1个参谋负责提议进攻时间;每支军队也有1个将军批准参谋提出的进攻时间;很明显,1个参谋提出的进攻时间需要获得至少2个将军的批准才有意义;
5) 问题:是否存在一个协议,能够使得蓝军同步他们的进攻时间?
接下来以两个假设的场景来演绎BasicPaxos;参谋和将军需要遵循一些基本的规则
1) 参谋以两阶段提交(prepare/commit)的方式来发起提议,在prepare阶段需要给出一个编号;
2) 在prepare阶段产生冲突,将军以编号大小来裁决,编号大的参谋胜出;
3) 参谋在prepare阶段如果收到了将军返回的已接受进攻时间,在commit阶段必须使用这个返回的进攻时间;
两个参谋先后提议的场景
1) 参谋1发起提议,派通信兵带信给3个将军,内容为(编号1);
2) 3个将军收到参谋1的提议,由于之前还没有保存任何编号,因此把(编号1)保存下来,避免遗忘;同时让通信兵带信回去,内容为(ok);
3) 参谋1收到至少2个将军的回复,再次派通信兵带信给3个将军,内容为(编号1,进攻时间1);
4) 3个将军收到参谋1的时间,把(编号1,进攻时间1)保存下来,避免遗忘;同时让通信兵带信回去,内容为(Accepted);
5) 参谋1收到至少2个将军的(Accepted)内容,确认进攻时间已经被大家接收;
6) 参谋2发起提议,派通信兵带信给3个将军,内容为(编号2);
7) 3个将军收到参谋2的提议,由于(编号2)比(编号1)大,因此把(编号2)保存下来,避免遗忘;又由于之前已经接受参谋1的提议,因此让通信兵带信回去,内容为(编号1,进攻时间1);
8) 参谋2收到至少2个将军的回复,由于回复中带来了已接受的参谋1的提议内容,参谋2因此不再提出新的进攻时间,接受参谋1提出的时间;
两个参谋交叉提议的场景
1) 参谋1发起提议,派通信兵带信给3个将军,内容为(编号1);
2) 3个将军的情况如下
a) 将军1和将军2收到参谋1的提议,将军1和将军2把(编号1)记录下来,如果有其他参谋提出更小的编号,将被拒绝;同时让通信兵带信回去,内容为(ok);
b) 负责通知将军3的通信兵被抓,因此将军3没收到参谋1的提议;
3) 参谋2在同一时间也发起了提议,派通信兵带信给3个将军,内容为(编号2);
4) 3个将军的情况如下
a) 将军2和将军3收到参谋2的提议,将军2和将军3把(编号2)记录下来,如果有其他参谋提出更小的编号,将被拒绝;同时让通信兵带信回去,内容为(ok);
b) 负责通知将军1的通信兵被抓,因此将军1没收到参谋2的提议;
5) 参谋1收到至少2个将军的回复,再次派通信兵带信给有答复的2个将军,内容为(编号1,进攻时间1);
6) 2个将军的情况如下
a) 将军1收到了(编号1,进攻时间1),和自己保存的编号相同,因此把(编号1,进攻时间1)保存下来;同时让通信兵带信回去,内容为(Accepted);
b) 将军2收到了(编号1,进攻时间1),由于(编号1)小于已经保存的(编号2),因此让通信兵带信回去,内容为(Rejected,编号2);
7) 参谋2收到至少2个将军的回复,再次派通信兵带信给有答复的2个将军,内容为(编号2,进攻时间2);
8) 将军2和将军3收到了(编号2,进攻时间2),和自己保存的编号相同,因此把(编号2,进攻时间2)保存下来,同时让通信兵带信回去,内容为(Accepted);
9) 参谋2收到至少2个将军的(Accepted)内容,确认进攻时间已经被多数派接受;
10) 参谋1只收到了1个将军的(Accepted)内容,同时收到一个(Rejected,编号2);参谋1重新发起提议,派通信兵带信给3个将军,内容为(编号3);
11) 3个将军的情况如下
a) 将军1收到参谋1的提议,由于(编号3)大于之前保存的(编号1),因此把(编号3)保存下来;由于将军1已经接受参谋1前一次的提议,因此让通信兵带信回去,内容为(编号1,进攻时间1);
b) 将军2收到参谋1的提议,由于(编号3)大于之前保存的(编号2),因此把(编号3)保存下来;由于将军2已经接受参谋2的提议,因此让通信兵带信回去,内容为(编号2,进攻时间2);
c) 负责通知将军3的通信兵被抓,因此将军3没收到参谋1的提议;
12) 参谋1收到了至少2个将军的回复,比较两个回复的编号大小,选择大编号对应的进攻时间作为最新的提议;参谋1再次派通信兵带信给有答复的2个将军,内容为(编号3,进攻时间2);
13) 将军1和将军2收到了(编号3,进攻时间2),和自己保存的编号相同,因此保存(编号3,进攻时间2),同时让通信兵带信回去,内容为(Accepted);