假设您有n个进程,n> 2.您希望在它们之间达成协议,即一个进程是活动的.所以他们需要彼此投票以确定哪一个是活跃的.
所有进程都可能随时失败,我们希望尽可能让一个进程处于活动状态,但......
我们必须永远不要同时有两个活跃,所以如果他们不能确定没有一个活跃的更好.(即我们想避免裂脑)
它们之间唯一可用的通信机制是pub-sub消息传递(不是点对点).
可以使用一个或多个数据库,但没有一个数据库应该是单点故障.IE浏览器.如果所有流程都可以工作,那将是非常不受欢迎的,并且由于丢失了单个数据库而无法这样做.
设计?需要发布什么消息?
理论:
这是领导者选举,这是共识问题的一种形式,有时也被称为"两个将军问题".在一些假设(完全异步和消息可能丢失)下,它已被证明是不可能的,并且证明特别优雅.
这个问题的直觉是:假设存在一些允许在某些固定数量的消息中达成共识的算法.由于容忍了故障,我们可以从协议中删除一条消息,它仍然可以工作.我们可以重复这个过程,直到根本没有消息,显然是不可能的.
在实践中,我们使用故障检测器来模拟同步系统来克服这个问题.
解决共识的最广为人知的算法是Paxos,它可以容忍多达一半参与节点的失败.Paxos的声誉非常难以实现,因为即使对协议细节的轻微误解也会破坏它的正确性.
实用解决方案
虽然问题一般很困难,但是更容易实现工作系统.有现成的Paxos实现或等效算法可用.Apache Zookeeper是我所知道的最好的.对于您的具体问题,我很确定这将是您最快的路线.其他Paxos实现也存在,也可能在Wackamole等网络冗余虚拟ip工具上构建一些东西.我相信大多数商业数据库的高端版本提供仲裁功能作为(昂贵)选项.
此外,对于许多应用来说,稍微削弱正确性或以其他方式调整问题以允许更简单的解决方案是可接受的.
例如,如果单点故障是可以容忍的,因为恢复可能很快,那么问题就很简单:只需要一个特殊节点就可以完成工作.
另一种方法可能是围绕幂等操作构建系统,因此重复处理变得可以容忍.
最后,您可以将工作负载划分为非冗余系统池:此处故障将延迟处理直到恢复,但仅针对该节点处的项目,而不是整个工作负载.
这些妥协是如此简单,以至于它们通常是更好的选择.人们必须权衡完整解决方案的效用与实现它的复杂性,看看是否真的有价值.这就是为什么这么多实际系统只使用2阶段或3阶段提交,即使它们在某些情况下阻塞:与完全仲裁系统的复杂性相比,可用性降低是可以接受的.