Paxos算法原理与推导
一、问题产生的背景
在分布式系统中,必然会存在服务宕机或网络异常(如网络延迟、消息乱序、消息丢失等)等状况。Paxos基于容错的分布式环境,实现在集群内部对某个值达成最终一致的分布式算法。
【注1】服务不存在拜占庭将军问题(不存在叛徒),也即集群内的机器可以随时发生宕机重启,但不能做出有违约定的行为。
【注2】集群中的某个值可以是一条命令、一组数据等,value对每个应用场景具有不同的意义
二、相关概念
1、数学符号
2、性质
三、推导过程
四、算法模型
首先,假设每一位议员的律簿的正面用于按照顺序记录已经通过的法令,比较正式,不可更改。律薄的背面(便签的作用,可以擦写)用于记录不连续的法令,以后再誊抄到正面。另外,律薄的背面还要记录几个关于投票过程的重要信息:
v: 议员自己上次完成投票的投票编号
b: 新一轮投票中接收到的新投票编号
下面就讲解这6个步骤:
1、议员p根据自己律薄的记录,选择一个新的投票编号b(b>v)。然后给大厅的其他议员,发送通知消息NextBallot=b。
【注】定理2
2、议员q收到p发送的消息以后,找到自己在b之前参与的投票编号v(b>v),并返回v;如果不存在v就返回null。返回消息LastVote(b)=v 。注意,此时q会锁定v~b之间的投票,即:议员q只会对b进行投票。
【注】B3性质保持,锁定MaxVote
3、议员p收到大厅内所有议员的step2响应汇总成一个集合V,根据B3法则,选择出本轮投票的法令d,然后,给大厅内所有议员发送开始投票的消息BeginBallot (b, d)。
【注】定理2
4、议员q开始表决(投票就表示赞同),修改自己律薄上记录的上次投票编号v=b。如果不表决可是因为:收到另一个议员p1发起的新投票编号b1(b1>b),这样在step2中锁定范围包括了b,所以,此时不能完成b轮投票;或者因为睡着了而没有投票等等。
5、议员p收到大厅所有议员的投票,那么法令d表决通过,在律薄上记录法令d,然后发送Success(d)消息。
6、议员q在律薄上记录法令d。
【注】以上六个步骤,所有的角色都可以选择执行或者不执行(网络异常或宕机等状况),但不能违背规则(拜占庭将军问题)
五、算法改进
改进一:基础协议
在初级协议的基础上,增加了以下限制:
1.任意时间点,只能由一位牧师发起一轮投票。
2.在step2完成以后,议员q将锁定所有小于b的投票,这比初级协议更为严格。
注解:
这个阶段新增的两个约束,降低了多个议员同时发起多轮投票的混乱场景,保证了投票过程的一致性
改进二:完整的神会协议
基础协议保证了一致性,但是无法保证投票的可进展性,如:议员p什么时候发起投票,如果一直傻傻的等着,那么什么法令都无法通过;如果他是个急性子,未等到上一轮投票结束,又发起新的伦理,由于step2的锁承诺的原因,新的投票会阻塞旧的投票,不断发起新的投票,最后的结果还是没有法令通过。那么,完整协议需要解决的是协议的可进展性问题。
首先,需要选择一个总统(president)。同时,假设经过一段时间后,会议没有人员进出了,那么就认为接下来的T分钟内(原文未讲解T的制定规则)通过选举只会有一位总统。选举的方式就是每隔T-11分钟(11分钟是一个议员处理消息+传递消息时间,也就是保证在T时间结束之前,完成一次名字交换)议员把自己的名字告诉大家,如果在T分钟内,仍然没有收到比自己更大的名字,那么他就认为自己是总统。
然后,总统什么时候该发起投票呢,投票频率怎么样呢,所以,总统需要知道每个步骤需要的时间。假设前面提到的6个步骤,每个议员处理消息的时间至少需要7分钟,消息传递的时间至少需要4分钟。那么全程至少需要需要:7分钟*6个步骤 + 4分钟*5次消息传递=62分钟。但是,完成一轮投票的时间不是T-11+62分钟,为什么呢?接着说。
完整协议没有机制保证总统的律薄上一开始就记录了最新的法令条纹和投票信息,那么按照B1规则,选出的投票编号b,有可能不是最大的,所以在step3之后,发送投票表决的时候,会遭到其他议员的反对(step4),告诉总统最新的投票编号是b1(b1>b),所以,完整协议完成一轮投票的时间,可能是T+99(44分钟是总统收到投票编号太小的消息的时间,55分钟是完成step1-6的总时间,但不包括step6本身执行时间),为什么说可能呢,因为这里的44分钟不是必须的。
最终,只要议会大厅的大门关闭T+99分钟,就一定可以通过至少一部法令。
改进三:多法令并行的国会
1.自动补齐法令:总统在step1选择新投票编号b的时候,找到自己律薄中编号最大的法令n,然后发送NextBallot(b,n)给其他议员。当其他议员收到该消息以后,议员会返回自己律薄中纪录的>n的法令,同时向总统请求自己缺少的法令;当然,如果议员律簿中最大的法令,那么返回正常的LastVote(b)消息。(阶段四的投票编号冲突需要等到step4才发生,step5才能被总统感知,所以,这里的改进是非常有必要的。)
2.如何引入新法令:总统引入新法令前,需要学习一个多数集合(过半)的议员已经投过票的法令。所有通过的法令至少被一个多数集合的议员投过票。所以,总统可以查看自己的律薄就知道当前的法令是否已经全部通过,然后就可以提议新的法令了。
3.简化的投票:如果会议大厅的大门关闭,一段时间内没有人员出入,那么总统和议员是固定的,这时候的投票就很简单了,只需要step3-5即可以完成一轮投票。甚至总统可将上一轮投票的step5消息和这一轮的step3消息合并为一个消息发送,这就变成了是一个高效的议会。
六、工程性问题
1.关于选择一个新总统的问题:议员z出海捕鱼半年后回到议会大厅,他立刻当选为新的总统(因为他的名字的字母顺序是最大的),那么在他开始发起投票之前,必须先学习这半年的法令,这将是一个漫长的过程,而在此期间议会一直处于等待状态。
2.长长的律薄:经过长期积累,律薄会变得很长。而同一件事情(如:羊毛的价格)也会被不断更新,事实上大家只需要知道最后一次通过的相关法令即可。
3.官僚化:原文中提的这一点,我觉得和“法令的学习”是一致的。
4.法令的学习:随着法令的增加,同一件事的新旧法令也越来越多,如何保证两个农民能学习到一致的法令(或者有分歧时如何统一),这就需要为每一个领域指定一位议员做该领域的专家,负责解释该领域的最新法令。
5.不诚实的议员和无心之失:这两种情况都会导致议员之间法令的不一致,如何保证议会系统的自稳定性,很不幸,暂时还没有被发掘。
6.选举新的议员:由于法令需要过半数议员的同意才能通过,如果当前法令选举了大量新的议员,而这些议员又无法参加议会(如:已故、长期出海等),这样议会就停摆了。