15

假设您有 n 个进程,n > 2。您希望它们之间达成一致,即其中一个是活动的。所以他们需要互相投票来决定哪一个是活跃的。

所有进程都可能随时失败,如果可能,我们希望有一个进程处于活动状态,但是......

我们不能同时有两个活动,所以如果他们不能确定最好没有一个活动。(即,我们要避免脑裂)

它们之间唯一可用的通信机制是发布-订阅消息(不是点对点)。

有一个或多个数据库可用,但没有一个数据库应该是单点故障。IE。如果所有进程都可以工作,并且由于丢失单个数据库而无法这样做,那将是非常不可取的。

设计?需要发布哪些消息?

4

3 回答 3

31

理论:

这是领导人选举,是共识问题的一种形式,有时也称为两将军问题。在某些假设下(完全异步和消息可能丢失)已被证明是不可能的,而且证明特别优雅。

这个问题的直觉是:假设存在某种算法,允许在一些固定数量的消息中达成共识。由于可以容忍失败,我们可以从协议中删除一条消息,它应该仍然有效。我们可以重复这个过程,直到完全没有消息,这显然是不可能的。

在实践中,我们使用故障检测器来模拟同步系统来克服这个问题。

解决共识的最广为人知的算法是Paxos,它可以容忍多达一半的参与节点失败。Paxos 以难以实现而著称,因为即使对协议细节的轻微误解也会破坏它的正确性。

实际解决方案:

虽然这个问题一般来说相当困难,但启动工作系统要容易得多。有现成的 Paxos 实现或等效算法可用。Apache Zookeeper是我所知道的最好的。对于您的具体问题,我很确定这将是您最快的路线。其他 Paxos 实现已经存在,也有可能在Wackamole等网络冗余虚拟 ip 工具上构建一些东西。我相信大多数商业数据库的高端版本都提供仲裁功能作为(昂贵的)选项。

此外,对于许多应用程序,稍微削弱正确性或以其他方式调整问题以允许更简单的解决方案是可以接受的。

例如,如果单点故障是可以容忍的,因为恢复可能很快,那么问题就很简单了:只需要一个特殊的节点来完成工作。

另一种方法可能是围绕幂等操作构建系统,因此可以容忍重复处理。

最后,您可以将工作负载划分到一个非冗余系统池中:这里的故障将延迟处理直到恢复,但仅针对该节点上的项目,而不是整个工作负载。

这类妥协非常简单,以至于它们通常是更好的选择。人们必须权衡一个完整解决方案的实用性与实施它的复杂性,看看是否真的有价值。这就是为什么这么多实际系统只使用2 Phase3 Phase Commit的原因,即使它们在某些情况下会阻塞:与完整仲裁系统的复杂性相比,可用性降低是可以容忍的。

于 2009-07-10T01:41:27.417 回答
1

我不清楚发布-订阅消息。

如果他们从外部来源获取某种工作对象,而您只希望其中一个处理工作,则可以取一个哈希值空间 2^64,将空间除以每个节点占用的节点数一块。每个节点都可以在工作对象进入时对其进行哈希处理并确定它是否属于他们。

于 2009-07-10T01:26:27.950 回答
0

看看路由协议(OSPF 和 IS-IS)是如何做到的,看看它是否适合你。他们选举一个领导者(在 OSPF 的情况下,一个备用领导者)。

于 2009-08-26T19:42:50.840 回答