ZooKeeper构建一个高可用的集群。

集群组成

        要搭建一个高可用的ZooKeeper集群,我们首先需要确定好集群的规模。关于ZooKeeper集群的服务器主城,都存在或曾经存在过这样一个错误的认识:为了使得ZooKeeper集群能够顺利的选举出Leader,必须将ZooKeeper集群的服务器数部署成奇数。这里我们需要澄清的一点是:任意台ZooKeeper服务器都能部署且能够正常运行。

        其实关于ZooKeeper集群服务器数,ZooKeeper官方确实给出了关于奇数的建议,但绝大部分ZooKeeper用户对这个建议认识有偏差。基于“过半存活即可用”这个特性,如果想搭建一个能够允许F台及其down掉的集群,那么就要部署一个由2*F+1台服务器构成的ZooKeeper集群。因此,一个由3台机器构成的ZooKeeper集群,能够在挂掉1台机器后依然正常工作,而对于一个由5台服务器构成的ZooKeeper集群,能够对2台机器挂掉的情况容灾。注意,如果是一个由6台服务器构成的ZooKeeper集群,同样只能够挂掉2台机器,因为如果挂掉3台,剩下的机器就无法实现过半了。

        因此,从上面的讲解中,我们其实可以看出,对于一个由6台机器构成的ZooKeeper集群来说,和一个由5台机器构成的ZooKeeper集群相比,其在容灾能力上并没有任何显著的又是。基于这个原因,ZooKeeper集群通常设计部署成奇数台服务器即可。

容灾

        所谓容灾,在IT行业通常是指我们的计算机信息系统具有的一种在遭受诸如火灾、水灾、地震、断电和其他基础网络设备故障等毁灭性灾难的时候,依然能够对外提供可用服务的能力。

        对于一些普通的应用,为了达到容灾标准,通常我们会选择在多台机器上进行部署来组成一个集群,这样即使在集群的一台或是若干台机器出现故障的情况下,整个集群依然能够对外提供可用的服务。

        而对于一些核心应用,不仅要通过使用多台机器构建集群的方式来提供服务,而且还要将集群中的机器部署在两个机房,这样的话,即使其中一个机房遭遇灾难,依然能够对外提供可用的服务。

        上面讲到的都是应用层面的容灾模式,那么对于ZooKeeper这种底层组件来说,如何进行容灾呢?ZooKeeper既然已经解决了单点问题,那么为什么还要进行容灾呢?

单点问题

        单点问题是分布式环境中最常见也是最经典的问题之一,在很多分布式系统中都会存在这样的单点问题。具体的说,单点问题是指在一个分布式系统中,如果某一个组件出现故障就会引起整个系统的可用性大大下降甚至是处于瘫痪状态,那么我们就认为该组件存在单点问题。

        ZooKeeper确实已经很好的解决了单点问题。基于“过半”设计原则,ZooKeeper在运行期间,集群中至少有过半的机器保存了最新的数据。因此,只要集群中超过半数的机器还能够正常工作,整个集群就能够对外提供服务。

容灾

        解决了单点问题,是否就不需要考虑容灾了呢?答案是否定的,在搭建一个高可用的集群的时候依然需要考虑容灾问题。正如上面讲到的,如果集群中超过半数的机器还在正常工作,集群就能够对外提供正常的服务。那么如果整个机房出现灾难性的事故,这时显然已经不是单点问题的范畴了。

        在进行ZooKeeper的容灾方法设计过程中,我们要充分考虑到“过半”原则。也就是说,无论发生什么情况,我们必须要保证ZooKeeper集群中有超过半数的机器能够正常工作。因此通常有以下两种部署方案。

三机房部署

        在进行容灾方案设计的时候,我们通常是以机房为单位来考虑问题的。假如我们有三个机房可以部署服务,并且这三个机房间的网络情况良好,那么就可以在三个机房中都部署若干个机器来组成一个ZooKeeper集群。

        我们假定构成ZooKeeper集群的机器总数为N,在三个机房中部署的ZooKeeper服务器数分别为N1、N2和N3,那么如果要使该ZooKeeper集群具有容灾能力,我们可以根据如下算法来计算ZooKeeper集群的机器部署方案。

计算N1

        如果ZooKeeper集群的服务器总数是N,那么N1 = (N-1)/2。注意,在Java中,“/”运算符会自动对计算结果进行向下取整操作。举个例子,如果N为8,那么N1为3,如果N为7,那么N1也为3。

计算N2的可选值

        N2的计算规则和N1非常类似,只是N2的取值是在一个取值范围内:

  • N2的取值值范围是1~ (N-N1)/2

        即如果N为8,那么N1则为3,于是N2的取值范围就是1~2,分别是1和2。注意,1和2仅仅是N2的可选值,并非最终值——如果在N2为某个可选值的时候,无法计算出N3的值,那么该可选值也无效。

计算N3,同时确定N2的取值

        很显然,现在只剩下N3了,可以简单地认为N3的取值就是剩下的机器数,即:

N3 = N - N1 - N2

        只是N3的取值必须满足N3 < N1 + N2。在满足这个条件的基础下,我们遍历步骤2中计算得到的N2的可选值,即可得到三机房部署时每个机房的服务器数量了。

        现在我们以7台机器为例,来看看如何分配三机房的机器分布。根据算法的步骤1,我们首先确定N1的取值为3.根据算法的步骤2,我们算法的步骤2,我们再确定了N2的可选值为1和2。最后在步骤3中,我们遍历N2的可选值,即可得到两种部署方案,分别是(3,1,3)和(3,2,2)。下面所示的Java程序代码是对上述算法的一个简单实现。

双机房部署

        上面我们讲到了如何在三机房中部署ZooKeeper集群来实现容灾。但是在实际情况中,很多公司的机房规模无法达到三机房的条件,因此双机房部署成为了更为现实的方案。但是很遗憾的是,在目前版本(3.4.6)的ZooKeeper中,还没有办法能够在双机房条件下实现较好的容灾效果——因为无论哪个机房发生异常情况,都有可能使得ZooKeeper集群中可用的机器无法超过半数。当然,在拥有两个机房的场景下,通常有一个机房是主要机房(一般而言,公司会花费更多的钱去租用一个稳定性更好、设备更可靠的机房,这个机房就是主要机房,而另一个机房的租用费相对而言则廉价一些)。我们唯一能做的,就是尽量在主要机房中部署更多的机器。例如,对于一个由7台机器组成的ZooKeeper集群,通常在主要机房中部署4台机器,剩下的3台机器部署到另一个机房中。

扩容与缩容

        水平可扩容可以说是对一个分布式系统在高可用性方面提出的基本的,也是非常重要的一个要求,通过水平扩容能够帮助系统在不进行或进行极少改进工作的前提下,快速提高系统对外的服务支撑能力。简单的讲,水平扩容就是向集群中添加更多的机器,以提高系统的服务容量。

        很遗憾的是,ZooKeeper在水平扩容方面做的并不十分完美,需要进行整个集群的重启。通常有两种重启方式:一种是集群整体重启,另一种是逐台进行服务器的重启。

整体重启

        我们先来看第一种集群整体重启的方式。所谓集群整体重启,就是先将整个集群停止,然后更新ZooKeeper的配置,然后再次启动。如果在你的系统中,ZooKeeper并不是一个非常核心的组件,并且能够允许短暂的服务停止(通常是几秒钟的时间间隔),那么不妨选择这种方式。在整体重启的过程中,所有该集群的客户端都无法连接上集群。等待集群再次启动后,这些客户端就能够自动连接上——注意,整体重启前建立起的客户端会话,并不会因为此次整体重启而失效。也就是说,在整体重启期间花费的时间将不计入会话超时时间的计算中。

逐台重启

        第二种逐台重启的方式似乎更适合绝大多数的实际场景。在这种方式中,每次仅仅重启集群中的一台机器,然后逐台对整个集群中的机器进行重启操作。这种方式可以在重启期间依然保证集群对外的正常服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值