在上篇文章中《memcached/redis比较 缓存代理比较(Twemproxy/Codis/Redis-cluster)》 提到了paxos算法(basic Paxos)。本文就是我个人对其的理解(入门)
Paxos角色
paxos算法中,有以下几个角色存在:
Proposer(提议者)
Acceptor(接受者)
Learners(学习者)
某台server,可以兼具以上多种角色。
Paxos是什么
Paxos 算法是分布式一致性算法用来解决一个分布式系统如何就某个值(决议)达成一致的问题。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个”一致性算法”以保证每个节点看到的指令一致。这里想提一下一些中文的paxos算法理解的文章中用分布式系统竞争锁的场景作例子介绍paxos算法的过程,就我个人感觉不是很合适,因为paxos算法是一个较高效的一致性算法,和传统的分布式锁算法还是不太一样的,比如RA算法,它和单机上的加锁解锁有一个最大的共同点就是有很明显的“请求–等待”的过程,而paxos算法每一个实例之间相对独立,选举过程可以平行执行,后发生的实例是可以再先发生的实例之前表决的,并没有明显的“请求–等待”的感觉。在具体的应用时,分布式锁算法更多的是“互斥”的感觉,一致性算法更多的是“同步”的感觉。
本推导过程是摘录自 王下邀月熊_Chevalier的《分布式一致性算法Paxos介绍》
这里以具体例子来说明Paxos的整个具体流程: 假如有Server1、Server2、Server3这样三台服务器,我们要从中选出leader,这时候Paxos派上用场了。整个选举的结构图如下:
Phase1(准备阶段)
1.每个Server都向Proposer发消息称自己要成为leader,Server1往Proposer1发、Server2往Proposer2发、Server3往Proposer3发;
2.现在每个Proposer都接收到了Server1发来的消息但时间不一样,Proposer2先接收到了,然后是Proposer1,接着才是Proposer3;
3.Proposer2首先接收到消息所以他从系统中取得一个编号1,Proposer2向Acceptor2和Acceptor3发送一条,编号为1的消息;接着Proposer1也接收到了Server1发来的消息,取得一个编号2,Proposer1向Acceptor1和Acceptor2发送一条,编号为2的消息; 最后Proposer3也接收到了Server3发来的消息,取得一个编号3,Proposer3向Acceptor2和Acceptor3发送一条,编号为3的消息;
4.这时Proposer1发送的消息先到达Acceptor1和Acceptor2,这两个都没有接收过请求所以接受了请求返回[2,null]给Proposer1,并承诺不接受编号小于2的请求;
5.此时Proposer2发送的消息到达Acceptor2和Acceptor3,Acceprot3没有接收过请求返回[1,null]给Proposer2,并承诺不接受编号小于1的请求,但这时Acceptor2已经接受过Proposer1的请求并承诺不接受编号小于的2的请求了,所以Acceptor2拒绝Proposer2的请求;
6.最后Proposer3发送的消息到达Acceptor2和Acceptor3,Acceptor2接受过提议,但此时编号为3大于Acceptor2的承诺2与Accetpor3的承诺1,所以接受提议返回[3,null];
7.Proposer2没收到过半的回复所以重新取得编号4,并发送给Acceptor2和Acceptor3,然后Acceptor2和Acceptor3接收到编号为4的提议,因为4大于3,所以接受提议返回[4,null];
Phase2(决议阶段)
1.Proposer3收到过半(三个Server中两个)的返回,并且返回的Value为null,所以Proposer3提交了[3,server3]的议案;
2.Proposer1收到过半返回,返回的Value为null,所以Proposer1提交了[2,server1]的议案;
3.Proposer2收到过半返回,返回的Value为null,所以Proposer2提交了[4,server2]的议案;
4.Acceptor1、Acceptor2接收到Proposer1的提案[2,server1]请求,Acceptor2承诺编号大于4所以拒绝了通过,Acceptor1通过了请求;
5.Proposer2的提案[4,server2]发送到了Acceptor2、Acceptor3,提案编号为4所以Acceptor2、Acceptor3都通过了提案请求;
6.Acceptor2、Acceptor3接收到Proposer3的提案[3,server3]请求,Acceptor2、Acceptor3承诺编号大于4所以拒绝了提案;
7.此时过半的Acceptor都接受了Proposer2的提案[4,server2],Larner感知到了提案的通过,Larner学习提案,server2成为Leader;
问题与理解
1.在推导过程中用到的数字编号1,2,3,4是否是全局的,如果全局,那么应该如何生成?
编号1,2,3,4是全局编号,多台server,应该从共同的地方获取。但是若从外部服务获取,会使此算法的实现变的不够独立,依赖其他服务。而这里,我个人觉得使用时钟编号,例如:年月日时分秒纳秒 构成的序列。
2.在整个推导过程中,server发送提案的方式,均发送给两台,为何在推导过程,不发送给多台呢?
可以尝试进行发送给全局进行推导,其结果是一致的。而这里只发送给两台,可以理解为,在真实环境下的发送过程也只是发送给半数以上的server,这样可以适当减少网络负载。
最后,再次推荐 王下邀月熊_Chevalier的《分布式一致性算法Paxos介绍》的博文,本博文将相应的约束条件,另外的实现方式都讲述了一下,讲的更深入。