关闭。这个问题是opinion-based .它目前不接受答案。
想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.
3年前关闭。
Improve this question
假设您有 n 个进程,n > 2。您希望它们之间达成一致,即其中一个是事件的。所以他们需要互相投票来决定哪一个是活跃的。
所有进程都可能随时失败,如果可能,我们希望有一个进程处于事件状态,但是......
我们绝不能同时有两个事件,所以如果他们不能确定最好没有一个事件。 (即,我们要避免脑裂)
它们之间唯一可用的通信机制是发布-订阅消息(不是点对点)。
有一个或多个数据库可用,但没有一个数据库应该是单点故障。 IE。如果所有进程都可以工作,并且由于丢失单个数据库而无法这样做,那将是非常不可取的。
设计?需要发布哪些消息?
最佳答案
理论:
这是领导人选举,是 Consensus Problem 的一种形式,有时也称为 The Two Generals Problem .在某些假设下(完全异步和消息可能丢失)已被证明是不可能的,而且证明特别优雅。
这个问题的直觉是:假设存在某种算法,允许在一些固定数量的消息中达成共识。由于可以容忍失败,我们可以从协议(protocol)中删除一条消息,它应该仍然可以工作。我们可以重复这个过程,直到完全没有消息,这显然是不可能的。
在实践中,我们使用故障检测器来模拟同步系统来克服这个问题。
解决共识的最广为人知的算法是Paxos ,它可以容忍多达一半的参与节点发生故障。 Paxos 以难以实现而著称,因为即使对协议(protocol)细节的轻微误解也会破坏它的正确性。
实际解决方案:
虽然这个问题一般来说相当困难,但启动工作系统要容易得多。有现成的 Paxos 实现或等效算法可用。 Apache Zookeeper是我所知道的最好的。对于您的具体问题,我很确定这将是您最快的路线。其他 Paxos 实现已经存在,也有可能在网络冗余虚拟 ip 工具上构建一些东西,如 Wackamole .我相信大多数商业数据库的高端版本都提供仲裁功能作为(昂贵的)选项。
此外,对于许多应用程序,稍微削弱正确性或以其他方式调整问题以允许更简单的解决方案是可以接受的。
例如,如果单点故障是可以容忍的,因为恢复可能很快,那么问题就很简单了:只需要一个特殊的节点来完成这项工作。
另一种方法可能是围绕幂等操作构建系统,因此可以容忍重复处理。
最后,您可以将工作负载划分到一个非冗余系统池中:这里的故障将延迟处理直到恢复,但仅针对该节点上的项目,而不是整个工作负载。
这类妥协非常简单,以至于它们通常是更好的选择。人们必须权衡一个完整解决方案的实用性与实现它的复杂性,看看是否真的有值(value)。这就是为什么这么多实际系统只使用 2 Phase 的原因。或 3 Phase Commit ,即使它们在某些情况下会阻塞:与完整仲裁系统的复杂性相比,可用性降低是可以容忍的。
关于messaging - 避免脑裂、投票和法定人数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1106984/