避免裂脑,投票和法定人数

时间:2009-07-09 23:38:24

标签: messaging

假设您有n个进程,n>你希望他们之间达成一致意见。所以他们需要相互投票才能确定哪一个是活跃的。

所有流程可能随时失败,我们希望尽可能让一个流程处于活动状态,但是......

我们必须在同一时间永远不会有两个活动,所以如果他们不能确定没有一个活跃的更好。 (即我们想避免裂脑)

它们之间唯一可用的通信机制是pub-sub消息传递(不是点对点)。

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

设计?需要发布什么消息?

3 个答案:

答案 0 :(得分:29)

理论值:

这是领导者选举,它是Consensus Problem的一种形式,有时也称为The Two Generals Problem。在一些假设(完全异步和消息可能会丢失)下,它已被证明是不可能的,并且证明特别优雅。

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

在实践中,我们使用故障检测器来模拟同步系统。

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

实用解决方案:

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

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

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

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

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

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

答案 1 :(得分:1)

我不清楚pub-sub消息。

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

答案 2 :(得分:0)

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