-->

Paxos的价值选择(paxos value choice)

2019-08-07 15:08发布

我读过关于维基页面和文件(的Paxos变得简单)上的Paxos。 不过,我仍然感到困惑的一些细节:

  1. 在1A阶段,并提议者包括它打算在提案受体选择价值?

  2. 1B阶段,受体应该返回,它如果有以前接受的价值。 什么是价值的续航时间? IOW,当它认为接受,当它被覆盖/下降了吗?

对续航时间的问题的一些更新。 IIUC,第一验收合格后,受体应该始终手边有一个以前接受的价值。 它是如何决定是否应该在未来的许诺(1B)相退货吗? 或者,当它决定要忘记的价值?


更新2,以更好地@MichealDeardeuff讨论:

我有Paxos的波纹管的认识:

通常,在工作流程的Paxos,受体应该始终手边有一个以前接受的价值。 并回答一个准备请求时,它会值回送的承诺响应。 而投保人需要检查,如果该值作为自身在上轮提出相同的值。 如果不是,投保人继续发送接受与受体的返回值的要求。 如果是,提议者然后继续发送接受用它打算在此轮发送值请求。

以上理解是否正确?

如果不正确,请你解释一下为什么?

如果它是正确的,我很困惑,因为Paxos的协议并没有明确说出来。 它只是陈述:

其中v是编号最高的提案的答复中的价值,或者是任何值,如果反应报告的提案。

但是,我的理解,投保人需要检查,看看是否被接受返回的值是相同的值,在最后一轮中提出的相同的提议者。 如果是,即使是与承诺响应中最高编号的提议的值,投保人仍然可以选择它想要的,如果没有通过受体返回值的任何值。

这是我想看看是否有任何引用支持理解的原因。

非常感谢!

Answer 1:

在1A阶段,并提议者包括它打算在提案受体选择价值?

投保人并不需要把它打算选择直到阶段2a的价值。 另见我的回答前面一个问题。

1B阶段,受体应该返回,它如果有以前接受的价值。 什么是价值的续航时间? IOW,当它认为接受,当它被覆盖/下降了吗?

从我的回答到另一个不同的问题,“一位接受应该接受的所有价值,除非它已经承诺不会接受。” 也就是说,它应该接受与圆-ID大于或等于圆-ID在它发送的最后一个响应的任何价值。

它必须接受的任何其他值的原因是,一个提议可以发现(如阶段1的结果),一个不同的值应为-或已经已经挑选的; 它然后广播这个值的所有受体。 当有多个提议者和/或网络分区中这种差异可能发生。


更新回答评论。

当接受部接受的值,它保存到该值,直到它接受另一个值。 (与此相伴它存储了一轮价值)。

1B阶段,接受器总是把它的价值,使投保人理清实际选择的值是什么。 它从来不会忘记它的当前值。 永远。

从受体接受的承诺后,投保人有系统的美景。 (注:这不一定是完整或最新观点。)

这可能是因为不同的受体已经由于一些争用不同的投保人接受不同的值。 因此,投保人选择具有最高圆ID值,并将值的所有受体。 这就是为什么受体值被允许改变。

在评论值得关注的是,这种破坏的Paxos。 事实并非如此。

但是,在我进入一个例子,我要强调,它更容易去思考的Paxos名为阶段和信息,而不是1A,1B,2A,2B。 我通常命名阶段的准备阶段和接受阶段。 具有消息1A作为准备,1B作为无极,图2a为接受,和图2b为接受。

现在,让我们来假设的例子中,人们往往给予,他们认为休息的Paxos。 假设我们有三个接受者A1,A2和A3。 A1和A2都已经接受值ABC在第1轮和A3选择了XYZ在第2轮(即从不同的提议)。 我们可以看到,A1和A2组成多数派和ABC已经“选择”。

沿着该假设的例子继续,一个提议发送准备(3)和从A2和A3,即无极接收回响应(ABC @ 1)和无极(XYZ @ 2)。 提议者认为XYZ具有最高的一轮,并将沿在接受阶段,对其他主机覆盖ABC。 和中提琴,Paxos的坏了,对不对?

否。问题是启动状态,这是不可能的。 让我来告诉你为什么。

首先,提出了一些建议,这是关键的Paxos正确运行:

命题A:对于A1和A2具有值ABC @ 1,一个提议必须已将接受(ABC @ 1),这意味着它必须已经接收到多数承诺的响应于发送准备(1)。

命题B:对于A3具有值XYZ @ 2,提议者必须已将接受(XYZ @ 2),这意味着它必须已经接收到多数承诺的响应于发送准备(2)。

而现在的证据:

情况1:A1和A2已经具有值ABC @ 1.由命题B,对于A3为具有值XYZ @ 2 它必须已经接收到多数从受体承诺。 由于值ABC是在大多数接受器的,然后将它们中的至少一个必须已将无极(ABC @ 1)。 随着1为最高圆形标识,投保人必须选择值ABC和发送接受(ABC @ 2)。 但它没有,它发送接受(XYZ @ 2)。 一对矛盾。

案例2:A3的值已经是XYZ @ 2(记住,第2轮来临之前1轮:圆ID是每个投保人只能单调递增)由命题A,对A1和A2具有价值ABC @ 1,投保人必须获得过半数来自受体承诺。 同样,由命题B,对A3拥有它,也必须获得过半数承诺。 这意味着一定有在集合{A1,A2}即许两次至少一个受体。

壳体2a:接受器发送无极(1)第一,然后无极(2)。 然后,当它接收到的消息接受(ABC @ 1),它必须拒绝它,因为它已经承诺接受大于2早期没有价值,但因为它的价值ABC @ 1.矛盾并没有拒绝它。

壳体2b:接受器发送无极(2)第一个。 然后,当接收到消息准备(1),它必须拒绝它,因为它已经承诺了较高的圆。 但它显然没有,因为,由命题A,它发出的承诺(1)。 一对矛盾。

哇!

我希望这能够帮到你。


更新2:这是一个伪Python实现的Paxos的

from itertools import count
from concurrent import futures



class Acceptor():
    def __init__(self):
        self.acceptedValue = None
        self.acceptedRound = None

        self.promisedRound = None

    def onPrepare(self, message):
        if self.promisedRound > message.round:
            send(message.source, new Nack())

        self.promisedRound = message.round
        response = new Promise(round=self.acceptedRound, value=self.acceptedValue)
        send(message.source, response)

    def onAccept(self, message):
        if self.promisedRound > message.round:
            send(message.source, new Nack())

        self.acceptedValue = message.value
        self.acceptedRound = message.round
        send(message.source, new Accepted())




class Proposer():

    def __init__(self, selfId, quorum):
        self.quorum = quorum
        self.id = selfId

        # get a unique starting round, 
        # assumes acceptors and proposers are on same hosts
        self.initialRound = sorted(quorum).index(selfId)

    def propose(self, value):
        "Propose a value to be chosen; returns actual value chosen"

        # round is always unique to a proposer
        # count(start, step) returns an infinite sequence
        for round in count(self.initialRound, len(self.quorum))
            promises = self.prepare(round)

            if not promises: continue

            # interpret the prepare phase results, may be None
            selectedValue = max(promises, key=lambda p: p.round or -1)

            accepted = self.accept(round, selectedValue or value)

            if accepted: return value

    def prepare(self, round):
        "Drive the Prepare phase. returns the promises from the acceptors or None"

        message = new Prepare(round, source=self.id)
        responses = []
        for acceptor in self.quorum:
            responses.append(send(acceptor, message)))

        # wait for the results
        promises = []
        for response in futures.as_completed(responses):
            if response.exception(): continue # message died

            message = response.result()
            if not isinstance(message, Promise):
                # A nack message; abort the round. We may have got a majority,
                # but this speeds up the case when we didn't.
                return None

            promises.append(message)
            if (len(promises) > len(self.quorum) / 2:
                return promises

        # No majority of responses
        return None

    def accept(self, round, value):
        "Drive the Accept phase. returns True iff the value was accepted"

        message = new Accept(round, value)
        responses = []
        for acceptor in self.quorum:
            responses.append(send(acceptor, message)

        # wait for the results
        accepts = 0
        for response in futures.as_completed(responses):
            if response.exception(): continue # message died

            message = response.result()
            if not isinstance(message, Accepted):
                # A nack message; abort the round. We may have got a majority,
                # but this speeds up the case when we didn't.
                return False

            accepts = accepts + 1
            if accepts > len(self.quorum) / 2:
                return True

        # No majority of responses
        return False

更新3回答从评论更多的问题。

......如果是在最后一轮发送相同的值提议者,我们要投保人忽略它(否则我们最终在一个死循环,对吧?)

(我假设“忽略”的值指早退出循环。)

首先,请注意,当从提议的大部分这样的值,已被选择的受体的接收确认中的循环结束。 因此,如果投保人发现自己做后续准备阶段,你可以肯定的是它与另一提案人争或某些网络分区发生。 二,请注意准备阶段返回即使只有一个接受器接受一个值的值(意味着该值可能不已经被大多数人所接受。)

如果在一个值准备阶段的结果,它是它在上一轮看到了同样的价值,它应当与接受阶段进行反正有几个原因。

  • 如果投保人早退出循环,这可能是因为其他投保人已经失败。 这可能会导致在被选择任何值。
  • 如果早退出循环,这是合理的其他提议者,以下相同的算法已经退出了环太; 再次导致可能没有值被选择。
  • 如果恰巧的值实际上已经选择了,这可能是因为不是所有的节点都收到值(由于网络分区)或有不同的值(由于与其他提议者这场斗争)。 这是件好事,那么,价值推到了耐用性的缘故节点。

在另一方面, 有可能的Paxos进入一个无限循环当有两个或更多的提议者和一些坏运气之间的竞争。 (这是任何共识算法的真实,是由里氏等人证明了之前的任何共识算法实际上是发现了。)所以理论上说,但在实际系统中很容易得到解决 :每个随后的一轮,暂停随机量时间让对方投保人有赢得比赛的机会。 当然,它仍然有可能有一个无限循环,但它不可能永远发生在宇宙的寿命。

你有任何引用来支持论点?

我从我自己的学习和经历讲居多。 我是一个团队,开发和维护为核心的Paxos与构建的系统。 我也做了广泛的研究课题。

下面是一些关于这个问题好论文:

  • Paxos的繁为简 (你说过你已经阅读过)
  • 该帕克森议会 (原纸)
  • 解构的Paxos (模块化了的Paxos成几个部件,他们然后调整为不同的场景)
  • 的Paxos的ABCDs (巴特勒·兰普森普及的Paxos,但他有时被混淆。)

更新的问题回答4次更新。

通常,在工作流程的Paxos,受体应该始终手边有一个以前接受的价值。 并回答一个准备请求时,它会值回送的承诺响应。 而投保人需要检查,如果该值作为自身在上轮提出相同的值。 如果不是,投保人继续发送接受与受体的返回值的要求。

好了,到目前为止。 但投保人并不需要保持两轮之间的状态。 我们很快就会找出原因。

如果是[相同的值],提议者然后继续发送接受用它打算在此轮发送值请求。

如果有任何值由接受退换,具有最高圆-ID 必须在接受阶段使用。 如果没有值由接受返回,比任何值可用于:我的逻辑表明,这将是值传递给投保人的客户端。

与此比较的Paxos繁为简 (第6页):

......其中v是编号最高的提案的答复中的价值,或者是任何值,如果反应报告的提案。

(这是一种很难说术语的文件之间切换。这里兰波特使用术语编号的建议 ,他们在其他地方,他使用的术语是圆的ID。有一个和相同的。)

假设要保人运行的准备阶段,并认为该受体之间的这种状态。

             A1   A2  A3
promise:      3    ?   4
value@round:  x@3  ?  y@4

在实际状态

              A1  A2  A3
promise:       3   4   4
value@round:  x@3 y@4 y@4

现在,假设它完成了上一轮与值y。 如果允许选择在这一点上的任何值,它可能会迫使这种状态:

              A1  A2  A3
value@round:  z@5 z@5 z@5

这将覆盖所选择的值,违反协商一致的一致性属性(维兹, 在可以选择最一个值。)。

如果你这样的行为,你不能因为是使用一致性协议。 您可以使用协议,如ABD ,或其他基于轮次的寄存器 。 或者,你能想到的Paxos作为选择的状态机的转变 。 换句话说,每次你想改变你运行一个新的Paxos算法来选择过渡的变量。 这是我的系统呢(而且我敢说,最实用的Paxos系统)。

请注意,在ABD和圆形为主的寄存器作用类似于Paxos的,但有点简单,因为他们没有保证上述一致性属性(一次选择,总是选择)。 但基于的Paxos状态机允许在变量CAS操作。



文章来源: paxos value choice
标签: cloud paxos