我正在编写一个相当复杂的 Go Web 应用程序,我希望它具有高可用性。我计划让多个虚拟机运行该应用程序,并使用负载均衡器根据我的需要引导它们之间的流量。
事情变得复杂的是,web 应用程序运行着一种数据库簿记例程,我在任何时候只需要(最多)一个实例。因此,如果我有三个 webapp 虚拟机,那么只有其中一个应该负责记账。
(是的,我知道我可以将簿记完全拆分到一个单独的 VM 实例中,但代码已与 Web 应用程序的其余部分高度集成。)
我花了几个小时查看类似 etcd 的内容, raft , bully , memberlist , Pacemaker , 等等等等。这些似乎都需要吸收大量信息来完成我所追求的目标,或者我看不到使用它们的明确方法。
在这个特定的用例中,我想要的是一个系统,Go webapp 节点可以自动检测彼此并选择一个“领导者”来进行记账。理想情况下,这可以扩展到 2 到 10 个节点,并且不需要手动将 IP 地址添加到配置文件(但如果需要,也是可以的)。
我在想,在网络分区或其他情况下,一个节点看不到其他节点,我不希望它选举自己作为领导者,因为可能有两个节点尝试做书-同时保持。这也意味着,如果我将集群剥离为单个虚拟机,则不会发生簿记,但在维护期间可以在短时间内容忍这种情况,或者我可以在某处设置某种标志。
我想知道是否有人可以为我指明正确的方向,并希望我如何以较低的复杂性实现这一目标,同时尽可能地利用现有的代码库。
最佳答案
根据您的容错性和一致性要求 - 特别是防止分区中的脑裂 - 像 Raft 这样的共识算法绝对是您想要的。但即使 Raft 的设计是为了易于理解,它仍然需要大量的专业知识才能正确实现。因此,正如其他人提到的,您应该研究现有的服务或实现。
ZooKeeper (ZAB),etcd (筏)和Consul (Raft)是执行此类操作最广泛使用的系统。考虑到您希望虚拟机从 2 个节点扩展到 10 个节点,这很可能是您想要的方式。 Raft 和其他共识算法具有仲裁要求,如果算法直接嵌入到虚拟机中,则这种方式的扩展不太实用。通过使用外部服务,您的虚拟机只需成为共识服务的客户端,并且可以独立于它进行扩展。
或者,如果您不想依赖外部服务进行协调,则Raft website有各种语言的详尽实现列表,其中一些是共识服务,一些可以嵌入。但请注意,其中许多内容并不完整。至少,任何适合生产的 Raft 实现都必须实现日志压缩。如果没有日志压缩,服务器实际上只能运行有限的时间 - 直到磁盘填满日志。
关于web-applications - Go Webapp集群领导者选举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35108372/