1 Introduction
可能是因为之前的描述对大多数读者来说太过Greek了,Paxos作为一种实现容错的分布式系统的算法被认为是难以理解的。但事实上,它可能是最简单,最显而易见的分布式算法了。它的本质其实就是共识算法——the "synod" algorithm of。在下一节中我们将展示,该共识算法基本满足了所有我们想要它满足的特性。最后一节则展示了完整的Paxos算法,通过直接应用协商一致的状态虚拟机来构建分布式系统——这种方法应该是广为人知的,因为这可能是分布式系统理论中被引用最多的领域。
2 The Consensus Algorithm
2.1 The Problem
假设有一些进程可以提出value。共识算法保证了在所有提出的value里只有一个会被选中。如果没有value被提出,那么也就没有value会被选中。如果一个value被选中了,那么其他的进程应该能够获取该value。协商一致的要求如下:
- 只能选择已经被提出的value
- 只能选择一个value
- 进程只能获取那些真正被选中的value
我们不会尝试指定精确的要求。但是我们的目标是要确保总有一些被提出的value会被选中,如果一个value最终被选中了,那么其他进程最终要能够获取该value。
我们用三类agent来代表共识算法中的三类角色:proposers, acceptors和learners。在具体的实现中,一个进程可能扮演不止一类agent,但是从agent到进程的映射我们在这里并不关心。
假设agent之间可以通过发送message互相通信。我们使用customary asychronous,non-Byzantine model,其中:
- Agents以任意速度执行,可能发生故障,可能重启。因为所有的agent都可能在一个value被选中之后故障并重启,因此一般的方法是不可行的,除非agent能记住一些信息,即使发生了故障或重启。
- 发送的message可以是任意长度的,可能重复,也可能丢失,但是它们不会被损坏
2.2 Choosing a Value
存在一个单一的acceptor agent是最简单的选择value的方式。proposer向acceptor发送提议,后者从中接收最早收到的那个。虽然很简单,但是这种方法是不能满足要求的因为acceptor的故障,因为acceptor的故障就将导致接下来的操作都无法进行。
因此我们需要尝试另一种选择值的方式。这次我们将有多个而不是一个acceptors。proposer将会向一个acceptor的集合发送value。acceptor可能会接受value。但是该value只有在足够多的acceptor都接受它的情况下才算被选择了。那么怎样才算足够大呢?为了确保只有一个value会被选中,我们可以认为一个足够大的agent集合由任意的agent majority组成。因为任意两个majority都至少有一个公共的agent,因此如果一个agent最多只能接收一个value,那么这种方法是可行的。
在没有故障和message丢失的情况下,我们想要有一个value能被选中,即使只有一个proposer提出了一个value。这就需要满足以下要求:
P1. acceptor必须接收第一个它收到的proposal
但是这个要求会引起这样一个问题。不同的proposer可能会在几乎同时提出好几个不同的value,这会导致这样一种情况:每个acceptor都接受了一个value,但是没有一个value是被一个majority接受的。即使只提出了两个value,而它们各自被一半的acceptor所接收,那么任意单个acceptor的故障都将让我们无法获取它选择了哪个value。
P1以及value只有被majority个acceptor接受才被算被选中的要求就导致了我们的acceptor必须能接受超过多于一个的proposal。我们通过给每个proposal赋予一个编号来追踪不同的proposal,所以一个proposal由一个proposal number和一个value组成。为了防止出现歧义,我们要求不同的proposal要有不同的number。这里我们仅仅只是做出这个假设,具体的实现可能有所不同。当一个proposal被一个acceptor的majority所接收时,我们就认为该value被选中了。这种情况下,我们说这个proposal(同时也包括它的value)被选中了。
我们可以允许多个proposal被选中,但是我们必须被选中的proposal必须有相同的value。