Paxos算法详解

Paxos解决的是分布式环境中的一致性问题。可以理解为:N个服务器要确定一个值Value等于多少,只要有多于半数的服务器还是存活并可以有效通信,那么这个值就可以通过Paxos算法确定下来,并且该值是唯一的。典型的问题如:选主。
  这个算法中有三个角色,提案者(proposer),接受者(acceptor)和学习者(learner)。每个服务器都可以兼职任何几种角色。在算法开始之前,每个proposer都知道整个环境中有多少个acceptor,即N的值是一开始就是确定了的。对proposer来讲,它需要提交两次请求,对acceptor来讲需要对proposer每次提出的请求做批准,即需要有二阶段提交。下面详细分析两个阶段以及两个阶段中的角色.

  • 第一阶段中的proposer:

  proposer发出该请求的前提条件:Value值还没有确定(其中Value值确定的条件是收到明确的消息“Value最终确定为某值”,收到该消息的过程中此proposer扮演的是learner角色)。
  proposer需要选取一个值作为自己的序列号K,这个序列号K要满足两个条件:第一,每个不同的proposer提交的序列号要严格不同;第二,对于每个proposer在Value值确定之前,可能需要提交多次序列号K,要确保该值一次比一次大。
  proposer需要将这个序列号S发送给至少大多数的服务器,即发给大于N/2个不同的acceptor(如果自己也是一个acceptor,那么是否可以发送给大于(N/2-1)个服务器呢?我的理解是:不可以,原因在于它不知道自己作为一个acceptor所存储的信息是什么,所以它可以选择向自己也发送这个请求,但是不能因此省略掉一次请求发送)。

  • 第一阶段中的acceptor:

  整个paxos算法过程中acceptor会保存两个信息:一个是自己回应过的最大序列号MaxN,如果还没有回应过则该值是空;另一个是在第二阶段批准过的决议对应的两个值:序号AcceptN和值AcceptV,这两个值在一开始也都为空。
  当收到来自proposer提交的带有唯一序列号K的请求后,它要做出回应,回应有三种:第一种,MaxN为空(即该acceptor第一次接受到此类请求),则直接同意并且做出承诺–从此之后不再回应序列号小于K的请求,且回应序号AcceptN和值AcceptV都为空;第二种,MaxN不为空且K>MaxN(也就是并非第一次接受此类请求,但是序列号K比以前回应过的都大),此时它要把自己保存的序号AcceptN和值AcceptV(即使都为空)发送给proposer,并且做出承诺–从此之后不再回应序列号小于K的请求;第三种,K<MaxN,序列号K太小了,基于以上做出的承诺,不做回应。
  从这个过程中可以看出,一旦acceptor在第二阶段接受了序号AcceptN和值AcceptV,那么它在第一阶段都会以他俩为基准告诉后来的proposer;acceptor还会在第一阶段不断做出承诺,它回应请求的前提是proposer提出的序列号要足够大。

  • 第二阶段中的proposer:

  proposer在第一阶段提交请求会收到回应,但是这个回应什么时候到达或者说会不会丢失消息是不确定的,所以在第二阶段开始之前proposer都会设置一个超时时间,一旦第一阶段中某个acceptor的回应晚于超时时间,那么proposer就认为没有收到。
  超时时间一过,proposer会首先检查一件事情,收到的回应个数有没有超过N/2。如果没有超过,那么此轮结束,proposer回到第一阶段重新开始。如果超过N/2,那么proposer会发起第二阶段的请求,发送给大于N/2个不同的acceptor。这个请求的内容就是自己的提案Value等于V,这个V值如何确定呢?它先检查自己在第一阶段获得的回应,如果所有的回应中都显示序号AcceptN和值AcceptV都为空,那么proposer就可以自己任选一个值作为V(例如在选主过程中选自己);否则选取所有收到的AcceptN最大的那个所对应的AcceptV作为V提交。
  这个过程中我们可以看到V的值取什么是很关键的,它会作为最终Value的备选值在下一步中进行批准,如果作为一个高效并且努力使Value唯一的算法,备选值应该越少越好,所以我们看到选择AcceptN最大所对应的值,这个在一定程度上保证了proposer所提出的v趋向于同一个值。
  在提交完同样还要等待acceptor的回应,同样这个回应也有一个超时时间,一旦回应超过半数同意,此刻Value的值最终确定了下来,然后proposer会通知所有learner该值已经确定,算法结束。但是如果在发出通知之前该acceptor挂了,那么其他的proposer继续执行,不过最终确定的Value一定是原来的那个。

  • 第二阶段中的acceptor

  acceptor做法非常简单,就是比较proposer在第二阶段提交过来的序列号是否大于自己的MaxN,如果大于,就直接同意,并且把自己相应的MaxN、序号AcceptN和值AcceptV进行更新;否则不予回应。

  整个算法看下来,有很多地方都是非常苛刻的,但是所有的步骤都在向同一个方向努力,无论期间有什么情况发生,都不会最终影响Value的确定性和唯一性。

http://coderxy.com/archives/136

你可能感兴趣的:(zookeeper)