繁体   English   中英

Lamport 的 Paxos 中的矛盾造就了简单的纸

[英]Contradiction in Lamport's Paxos made simple paper

阶段 2. (a) 如果提议者收到大多数接受者对其准备请求(编号为 n)的响应,那么它会向这些接受者中的每一个发送接受请求,以获得编号为 n 且值为 v 的提议,其中 v 是响应中编号最高的提案的值,或者如果响应未报告任何提案,则为任何值。

正如论文中提到的,

提议者通过向某组接受者发送提议被接受的请求来发布提议。 这不必是响应初始请求的同一组接受者。)”

但据我所知,如果我们将阶段 2.(a) 更改为:

如果提议者从大多数接受者那里收到对其准备请求(编号为 n)的响应,那么它会针对编号为 n 且值为 v 的提议向任意一组多数接受者发送接受请求,其中 v 是响应中编号最高的提案,或者如果响应未报告任何提案,则为任何值。

算法会失败,下面是一个例子。 考虑总共有 3 个受体 ABC。 我们将使用 X(n:v,m) 来表示接受者 X 的状态:proposal n:v 是被 X 接受的最大编号的提案,其中 n 是提案编号,v 是提案的价值,m 是X 曾经响应过的最大编号准备请求的编号。

  1. P1 向 AB 发送“准备 1”
  2. AB 都响应 P1 并承诺不接受任何编号小于 1 的请求。现在状态为: A(-:-,1) B(-:-,1) C(-:-,-)
  3. P1 接收到响应,然后卡住并且运行非常缓慢
  4. P2 向 AB 发送“准备 100”
  5. AB 都响应 P2 承诺不接受任何小于 100 的请求。现在状态是: A(-:-,100) B(-:-,100) C(-:-,-)
  6. P2 接收响应,选择值 b 并向 BC 发送“accept 100:b”
  7. BC接收并接受accept请求,状态为:A(-:-,100) B(100:b,100) C(100:b,-)。 请注意,已选择提案 100:b。
  8. P1 恢复,选择值 a 并向 BC 发送“accept 1:a”
  9. B 不接受,但 C 接受,因为 C 从未承诺过任何事情。 状态为:A(-:-,100) B(100:b,100) C(1:a,-)。 选择的提议是放弃,Paxos 失败。

我在这里错过了什么吗? 谢谢。

您在第 7 步中遗漏了一些内容。当 C 进程accept 100:b它会将其状态设置为C(100:b,100) 通过接受一个值,该节点还承诺不接受较早的值。


更新。 我整个月都在思考这个问题,因为我知道上面的答案并不完全正确。

更重要的是,我查看了几个专有和开源的 paxos 实现,它们都有 OP 提交的错误

因此,当完全从Paxos Made Simple 中查看时,这是正确的答案:

如果提议者从大多数接受者那里收到对其准备请求(编号为 n)的响应,那么它会向这些接受者中的每一个发送接受请求,以获得编号为 n 且值为 v 的提议,其中 v 是最高的值 -在响应中编号的提案,或者如果响应没有报告提案,则为任何值。 (强调我的)

换句话说,提议者只能将Accept消息发送给它已从该选票号码收到Promises接受者

那么,这是兰波特论文中的矛盾吗? 现在,我说是的。


如果您查看 Lamport 的 paxos 证明,他将accept视为promise ,正如我最初的回答所暗示的那样。 但这在Paxos Made Simple 中没有指出。 事实上,Lamport 似乎煞费苦心地指出accept不是promise

问题是当你结合两个变体的较弱部分时; 正如 OP 和几个实现所做的那样。 然后你会遇到这个灾难性的错误。

将接受请求广播给所有接受者当然没有问题。 您不需要将其限制为仅回复原始准备请求的那些。 你在兰波特博士的文章中发现了一个罕见的用词不当的案例。

但是,您的反例中有一个错误。 首先,符号定义如下:

X(n:v,m)表示接受者 X 的状态:提案n:v是 X 接受的编号最大的提案

但是在步骤 7 节点 C 具有状态C(100:b,-) ,然后在步骤 9 中它更改为状态C(1:a,-) 这不是一个有效的转换:在接受1:a它应该保持在状态C(100:b,-)因为100:b仍然是C 接受最大编号的提案

请注意,它在100:b之后接受1:a完全没问题,主要是因为网络是异步的,因此所有消息都可以延迟或重新排序而不会破坏任何内容,因此世界其他地方无论如何都无法分辨哪个提案首先被接受.

死灵。 即使两个变体的较弱部分,也没有不一致。 让我们看一下问题示例中的第 9 步:

“状态是 A(-:-,100) B(100:b,100) C(1:a,-)。选择的提案是放弃,Paxos 失败”

然而,此时我们只有一个不确定的值,因为没有多数人接受的值(我们最终必须选择“b”,因为 b 在步骤 6 中被多数人接受。)

为了继续协议,我们需要新的选票,最终一些新的选票将被接受。 该选票必须具有值“b”,

证明: C 将对任何准备请求响应 (100, 'b'),因为它接受的最高编号选票是 (100, 'b'),即使它最后接受了选票 (1, 'a')。 B 也会响应 (100, 'b')。 因此,不再可能获得除“b”以外的任何值的多数票。

Lamport 的语言是,acceptor 将回应“它已经接受的最高数字小于 n 的提案,如果有的话”

接受的答案将“最高编号”与“最新接受的”混淆,因为该示例表明接受者可以按编号递减的顺序接受值。 为了完全符合 Lamport 的协议,C 有必要记住它响应 (100, 'b') 即使它做出的“最新”接受是 (1, 'a')。

(话虽如此,如果许多实现没有正确执行此操作,因此很容易受到此问题的影响,我不会感到惊讶。)

论文中确实存在歧义,这就是为什么应该使用TLA+规范而不是论文来实现算法。

当接受一个值时,接受者必须再次更新其状态,即最近承诺的投票。 这在Paxos TLA+ 规范中很清楚,请查看接受器更新 maxBal 的阶段 2b,并与执行相同操作的阶段 1b 进行比较。

Leslie Lamport在他最近的演讲中处理了这个问题,他解释说,这样做是专门为了允许接受者集与承诺投票的节点集不同。

拉姆达

您的逻辑是合理的,但仅仅是因为您对Paxos算法的描述存在缺陷。 这应该是预期的,因为Paxos在数学上已被证明是正确的,你指出的问题是经典的争用案例之一。 我对古典Paxos文献的一个批评是,在我看来,这些论文并没有说明这样一个事实:算法的基本正确性要求是不同的同行不能重复使用提议编号。 每次提出提案时,它必须是唯一的,否则算法的正确性保证就会被抛出窗口。 如果允许重复使用,则会指出您指出的确切情况。 如果大家仔细阅读,你会看到,这是在经典论文中提到,但它不应该是度附近的任何地方强调。 应该使用粗体,下划线和恼人的文本。

为了说明这一点,在你的榜样改变你的提案ID的定义(又名回合数)是的(“poposal号”,“投保人唯一ID”)AA元组,而不是仅仅是一个整数,顺序被定义为a>b if a.proposal_number > b.proposal_number or a.proposer_unique_id > b.proposer_unique_id 你会看到你描述的问题消失了,算法完全正确。 您的示例确切方案描述了了解Paxos的“非案例”部分。 我可能会补充一个部分,我纯粹是因为我发现自己对你所指出的情景非常困惑。 很容易错过古典文献中的提案ID唯一性要求。

迈克尔在回答Paxos问题时通常是正确的,但在这种情况下,我认为他犯了一个小错误,再次归结于这一个主要的误解 - 不会发生 - 更好地强调 - 在原作中-papers-问题。 提议者不需要仅向那些使用Promise消息响应的对等体发送Accept消息。 在向所有对等方发送Accept消息时,无论是否响应Promise消息,该算法都是正确的, 只要保证提议ID对于每个对等方都是唯一的 尽管“Paxos Made Simple”论文的文字非常混乱...... Paxos真的很简单。 它确实依赖于对前期要求的充分理解,而Unique Proposal Ids绝对是其中之一。

Rakis

C 不能接受该提案,因为它尚未经过第 1 阶段。对于一个要被接受者接受的值的 IOW,接受者必须通过协议的两个阶段。

如果通过接受一个值,节点也承诺不接受早期的值,那么算法是正确的,但在论文中 Lamport 没有提到这个要求,对吧?

上述条件不是必需的。 假设接受者承诺的最高投票是 X。假设传入的接受消息的投票编号为 Y。如果 Y < X,我们知道 Y 必须被拒绝。 如果 Y > X,这意味着接受者没有收到 Y 的准备请求。这意味着,我们收到了无效的 paxos 消息。 在这种情况下,应该丢弃 Y 的接受消息。

唯一的例外是当 Y == 0 时。在这种情况下,发出带有投票编号 0 的准备没有意义,因为投票编号低于 0 是无效的。 因此,第 1 阶段可以跳过投票 0 并且提议者可以直接进入第 2 阶段。在这种情况下,即当 Y == 0 时,只有当它没有接受值时,接受者才能接受该值。 这与您在上面提出的建议相同,但仅在 Paxos 的优化版本中才需要,其中 Y == 0 可以跳过阶段 1。

IOWs,接受器接受一个值的唯一时间是当 Y == X 时。唯一的例外是当 Y == 0 时。在这种情况下,只有当它没有接受值时,接受器才能接受该值。

我同意 Ben Braun 的大部分回答。

C 可以接受 (1,a),它不会更改所选值。 假设 C 接受了 (1, a),我们从学习者的角度来看接受历史。

(100, b) 被 B 和 C 接受
(1, a) 被C接受

选择 (100, b) 是因为它被大多数接受者接受。

此时,如果学习者获得完整的接受历史,协议不需要继续,除非学习者失败或给学习者的消息丢失。 这就是我不同意 Ben Braun 的回答的地方。

但接受者应保留编号最高的已接受提案,以防发布新提案。

更新:我也同意 Dave Turner 的观点,即实际上没有理由接受编号较低的提案。 提案编号就像逻辑时钟,忽略旧消息是安全的。

Paxos Made Simple 中模棱两可的句子是“这不必是响应初始请求的同一组接受者”。

它的实际含义是“嗨,我在这里给你一个提示。可以优化本文中描述的算法,以消除准备阶段和接受阶段必须具有相同的接受者集的要求”。 请注意,Paxos Made Simple 中描述的算法与兼职议会中描述的算法略有不同。

但是,有人将那句话误解为这样:“本文描述的算法并不要求准备阶段和接受阶段必须具有相同的接受者集”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM