卡夫卡不停机,如何无感知迁移饲养员集群吗?

  

卡夫卡在Yelp的应用十分广泛,Yelp每天通过各种集群发送数十亿条消息,在这背后,卡夫卡使用管理员完成各种分布式协调任务。
因为Yelp非常依赖卡夫卡,那么问题来了,它是否可以在不引起卡夫卡及其他饲养员用户注意的情况下切换管理员集群呢?本文将揭晓答案。
卡夫卡在Yelp的应用十分广泛。事实上,我们每天通过各种集群发送数十亿条消息。在这背后,卡夫卡使用管理员完成各种分布式协调任务,例如决定哪个卡夫卡代理负责分配分区首领,以及在代理中存储有关主题的元数据。
卡夫卡在Yelp的成功应用说明了我们的集群从其首次部署卡夫卡以来经历了大幅的增长。与此同时,其他的动物园管理员重度用户(例如Smartstack和PaasTA)规模也在增长,给我们的共享饲养员集群添加了很多负担。为了缓解这种情况,我们决定让我们的卡夫卡集群使用专门的饲养员集群。
由于我们非常依赖卡夫卡,因维护造成的任何停机都会导致连锁反应,例如显示给业务所有者的仪表盘出现延迟,日志堆积在服务器上。那么问题就来了:我们是否可以在不引起卡夫卡及其他饲养员用户注意的情况下切换管理员集群?
管理员有丝分裂
经过团队间对卡夫卡和饲养员的几轮讨论和头脑风暴之后,我们找到了一种方法,似乎可以实现我们的目标:在不会导致卡夫卡停机的情况下让卡夫卡集群使用专门的饲养员集群。
我们提出的方案可以比作自然界的细胞有丝分裂:我们复制管理员主机(即DNA),然后利用防火墙规则(即细胞壁)把复制好的主机分成两个独立的集群。

  

卡夫卡不停机,如何无感知迁移饲养员集群?

  

有丝分裂中的主要事件,染色体在细胞核中分裂
让我们一步一步深入研究细节。在本文中,我们将会用到源集群和目标集群,源集群代表已经存在的集群,目标集群代表卡夫卡将要迁移到的新集群。我们要用到的示例是一个包含三个节点的饲养员集群,但这个过程本身可用于任何数量的节点。
我们的示例将为管理员节点使用以下IP地址:
源192.168.1.1-3
目标192.168.1.4-6
第1阶段:DNA复制
首先,我们需要启动一个新的饲养员集群。这个目标集群必须是空的,因为在迁移的过程中,目标集群中的内容将被删除。
然后,我们将目标集群中的两个节点和源集群中的三个节点组合在一起,得到一个包含五个节点的饲养员集群。这么做的原因是我们希望数据(最初由卡夫卡保存在源饲养员集群中)被复制到目标集群上.Zookeeper的复制机制会自动执行复制过程。
卡夫卡不停机,如何无感知迁移饲养员集群?

  

把来自源集群和目标集群的节点组合在一起
每个节点的动物园。cfg文件现在看起来都像下面这样,包含源集群的所有节点和目标集群中的两个节点:
server.1=192.168.1.1:2888:3888
server.2=192.168.1.2:2888:3888
server.3=192.168.1.3:2888:3888
server.4=192.168.1.4:2888:3888
server.5=192.168.1.5:2888:3888
注意,来自目标集群的一个节点(在上面的例子中是192.168.1.6)在该过程中保持休眠状态,没有成为联合集群的一部分,并且管理员也没有在其上运行,这是为了保持源集群的群体。
此时,联合集群必须重启。确保执行一次滚动重启(每次重启一个节点,期间至少有10秒的时间间隔),从来自目标集群的两个节点开始。这个顺序可以确保源集群的群体不会丢失,并在新节点加入该集群时确保对其他客户端(如卡夫卡)的可用性。
管理员节点滚动重启后,卡夫卡对联合集群中的新节点一无所知,因为它的饲养员连接字符串只有原始源集群的IP地址:
zookeeper.connect=192.168.1.1,192.168.1.2,192.168.1.3/卡夫卡
发送给管理员的数据现在被复制到新节点,而卡夫卡甚至都没有注意到。
现在,源集群和目标集群之间的数据同步了,我们就可以更新卡夫卡的连接字符串,以指向目标集群:
zookeeper.connect=192.168.1.4,192.168.1.5,192.168.1.6/卡夫卡
需要来一次卡夫卡滚动重启,以获取新连接,但不要进行整体停机。
第2阶段:有丝分裂
拆分联合集群的第一步是恢复原始源管理员及目标饲养员的配置文件(动物园。cfg),因为它们反映了集群所需的最终状态。注意,此时不应重启饲养员服务。
我们利用防火墙规则来执行有丝分裂,把我们的联合集群分成不同的源集群和目标集群,每个集群都有自己的首领。在我们的例子中,我们使用iptables来实现这一点,但其实可以两个管理员集群主机之间强制使用的防火墙系统应该都是可以的。

卡夫卡不停机,如何无感知迁移饲养员集群吗?