分布式一致性算法-paxos学习笔记

分布式一致性算法-paxos学习笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。

手动码字不易,请大家尊重劳动成果,谢谢

作者:http://blog.csdn.net/wang_wbq

Paxos算法描述

以下摘自Paxos Made Simple论文:

Phase 1.

(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors.

(b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered proposal (if any) that it has accepted.


Phase 2.

(a) If the proposer receives a response to its prepare requests (numbered n) from a majority of acceptors, then it sends an accept request to each of those acceptors for a proposal numbered n with a value v, where v is the value of the highest-numbered proposal among the responses, or is any value if the responses reported no proposals.

(b) If an acceptor receives an accept request for a proposal numbered n, it accepts the proposal unless it has already responded to a prepare request having a number greater than n.


Paxos算法的目的是为了在消息可能重复或丢失的情况下,在分布式系统中确定一个值的最终取值。

Paxos算法中有两个关键的角色组:proposeracceptor,其中acceptor组决定了整个分布式环境的一致性。先介绍下proposeracceptor的职责:

proposer为提案提出者,负责产生该值的可能性取值,并提交给acceptor进行决策。
proposer本地不持久化存储数据。

acceptor为决策者,负责批准或者拒绝一个proposer对该值的修改请求。
acceptor会在本地存储:
1、当前已收到的最大提案编号:PN,在未收到任何消息前,该值为空
2、当前最后一个批准的值的数据:Value,在未批准任何提案前,该值为空

首先来看下Paxos算法:

算法前提:所有proposer提出的提案编号不能重复。


第一阶段(预提案):

(a)proposer先选择一个提案编号N(我们假设所有proposer都从0开始),并且将该编号的预提交请求Prepare(N)发送给acceptor集合中的大多数服务(一般发送给全部acceptor集合)。

(b)如果一个acceptor接收到了一个提案编号为N的预提案请求Prepare(N),则比较其存储的最大提案编号PNN的关系:

1、如果PN为空,则先令PN = N,Value = null,并且同意proposer的该预提案请求,发送当前acceptor的最大提案编号PN(等于N)和最后一个批准的数据Value(为空):PrepareResponse(PN, null)
2、如果PN < N,则先令PN = N,Value = null,并且同意proposer的该预提案请求,发送当前acceptor的最大提案编号PN(等于N)和最后一个批准的数据Value(可能为空):PrepareResponse(PN, Value)
3、否则,拒绝该proposer的该预提案请求,发送当前acceptor的最大提案编号PN(大于N)和最后一个批准的数据Value(可能为空):PrepareResponse(PN, Value)


第二阶段(提案):

(a)当proposer的预提案Prepare(N)被acceptor集合中的大多数同意时(PN=N),则做出以下提案:

1、如果所有接收到的PrepareResponse(PN, Value)Value全部为空(acceptor还未批准任何提案),则自己制定一个该值的取值Vn,并向acceptor集合发送提案:Proposal(N, Vn)
2、如果接收到的PrepareResponse(PN, Value)集合中存在不为空的Value,则选取Value不为空的PrepareResponse(PN, ValueNotNull)集合PN最大的值(PNmax, ValueNotNull),并将其作为提案发送给acceptor集合:Proposal(PNmax, ValueNotNull)

(b)如果一个acceptor接收到一个提案编号为N的提案Proposal(N, Vn)则:

1、如果PN为空或者PN < N,则先令PN = N,Value = Vn,并且通过该条提案,返回:ProposalResponse(PN, Value)
2、如果PN == N并且Value为空(尚未批准提案号为PN的任何提案),则先令Value = Vn,并且通过该条提案,返回:ProposalResponse(PN, Value)
3、如果PN > N则拒绝该提案,返回:ProposalResponse(PN, Value)


以上为Paxos算法的一种解释方式,但是仅仅通过这两轮提交可能无法确定该值和取值:
1、只有acceptor集合中的大多数中的Value值都等于一个值时才能认定该值被确定
2、通过一次提交可能由于信息丢失导致不同的acceptor批准了不同值的提案的情况

因此为了确定该值的取值,可能需要多轮提案,下一轮提案的触发点的一种可能情况就是:

在proposer向acceptor提交预提案之后启动随机定时器,如果在超时前其预提案没有被大多数acceptor批准,则选取返回消息中最大的PN,在定时器超时后用PN + 1作为新的预提案号进行下一轮的二阶段提交。

Paxos算法合理性

paxos算法使用了集合中大多数这个保证来确定一个值是否可以被最终确定。比如N个节点集合的大多数为N / 2 + 1。比如有5个节点则取值为3,6个节点则取值为4,7个节点也取值为4。

为什么要使用集合中大多数这个概念呢,因为从集合全集中任取两个集合中大多数集合,那么这两个集合必定至少存在一个公共元素。这个元素就是整个paxos算法的关键要素。

以下证明思路非严格证明,只阐明思路

我们先假设一个值Value已经被一个acceptor集合的大多数批准了,我们试图思考下这个值是否还会被改变:

如果一个proposer要决定一个提案,必须先进行两阶段提交。首先进行预提案,只有提案编号大于acceptor中保存的提案编号的预提案才能被通过,因此proposer首先选取了一个足够大的提案编号进行预提案,acceptor会返回其接受的提案编号和当前已批准的值,由于算法规定proposer进行第二阶段提交前必须获得acceptor集合中的大多数同意,因此这个大多数acceptor集合中必定至少有一个acceptor已经批准了上述Value值,因此该提案必须使用这个提案编号最大的ValueX进行提案。

下面只需要证明这个提案编号最大的ValueX == Value即可保证值永远不会改变。

首先假设当前Value值被在提案号为N时被大都数acceptor批准了,因此在第N+1个提案时,其从大都数acceptor获取预提案反馈时必定会接收到值为Value的提案,并且其提案编号时最大的。因此第N+1个提案的Value值也必须为Value。以此类推,之后所有的提案都不会改变该Value值的取值。

以上思路说明了一旦一个值被大多数acceptor批准,则之后的提案不会再改变这个值(提案号还是会单调增加)。

Paxos活性

我们说明了如果遵循paxos算法,一个值被选定了,则这个值永远不会被改变,那是否存在这个值永远不会被选定的情况呢?

proposerA使用提案编号1进行预提案获得了大多数acceptor的通过,之后proposerB使用提案编号2进行预提案获得了大多数acceptor的通过,proposerA使用提案编号1进行提案则会被拒绝,之后又使用提案编号3进行预提案,proposerB使用提案编号2进行提交被拒绝,使用提案编号4进行预提案。。。。。。

以上这种情况下,paxos算法出现了活锁,因此一般在实际应用中,会首先使用paxos算法选举出一个leader,然后由该leader作为proposer来进行提案的二阶段提交,这样就消除了产生上述活锁的情况。并且因为paxos算法只能确定一个值的最终取值,往往不适用于实际应用中。通过首先选举leader的方式可以很好地控制实现一系列值的最终取值,也能保证所有proposer提出的提案编号不能重复这个前提条件。


参考资料:
1、Paxos Made Simple
2、《从Paxos到Zookeeper分布式一致性原理与实践》

posted @ 2018-05-19 14:03  海角Q  阅读(161)  评论(0编辑  收藏  举报