前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >容灾案例:Kafka集群快速扩容的方案总结

容灾案例:Kafka集群快速扩容的方案总结

原创
作者头像
邓愉悦
发布2021-08-20 11:32:17
1.2K0
发布2021-08-20 11:32:17
举报

熟悉Apache Kafka的同学都知道,当Kafka集群负载到达瓶颈或者出现突发流量需要紧急扩容时,新加入集群的节点需要经过数据迁移才能均分集群压力。而数据迁移会因为数据堆积量,节点负载等因素的影响,导致迁移时间较长,甚至出现迁移不动的情况。同时数据迁移也会增大当前节点的压力,可能导致集群进一步崩溃。

什么是数据迁移

Apache Kafka 对于数据迁移的官方说法是分区重分配。即重新分配分区在集群的分布情况。官方提供了kafka-reassign-partitions.sh脚本来执行分区重分配操作。其底层实现主要有如下三步:

  1. 通过副本复制的机制将老节点上的分区搬迁到新的节点上。
  2. 然后再将Leader切换到新的节点。
  3. 最后删除老节点上的分区。

重分配过程中最重要的一步是数据复制。故本文用数据迁移来形容这一行为,下面来看一下数据迁移的过程。

假设topicA有3个分区,2个副本,分区和副本分布在节点1和节点2。此时加了一个节点3,如果要让3个节点均分压力,就需要从节点1,2中迁移两个分区到节点3,如下所示:

图片
图片
图片
图片

扩容场景:

了解了数据迁移,我们来看下哪些场景需要进行扩容,然后有哪些方法可以实现快速扩容的效果。通常有如下两种需要紧急扩容的场景:

  • 集群所有节点负载都高,需要快速扩容。
  • 集群内某几台节点负载很高,需要降低这些节点的压力。

首先,来谈谈什么是节点压力。从我们的运营经验来说,Kafka集群的压力通常体现在磁盘util、CPU、网卡三个指标上。正常来说,通过加节点都可以解决这三个指标带来的问题。但是,从精细化运维的角度来说,可以有针对性地解决负载问题,达到不扩容就可以快速降低集群压力的目的。比如通过参数调优,踢掉某台故障节点/某块坏盘等等。

找到Top主题

根据二八法则和现网运营来看,在大多数集群中,头部效应一般都比较明显,即大部分压力都是由少量Topic带来的。所以一般只要解决导致问题的头部主题,就会事半功倍的解决问题。给大家看一下典型的现网集群的Topic流量排行示意图,集群的流量集中在下面的Top主题中:

图片
图片

图3:现网某集群topic流量排序图

另外,kafka-reassign-partitions.sh 分区迁移工具支持分区粒度的迁移,也可以支持整个Topic的迁移。所以在进行集群扩容的时候,不需要迁移所有的Topic。可以迁移某几个Topic或者某几个Topic中的某些分区。这样尽量减少需要搬迁的数据量。

那怎么样找到Top主题呢?

1. 如果系统内部有通过Broker暴露的的Jmx接口采集Topic入流量指标,那么对这些流量做一个排序,可以快速的找到目标主题。

2. 也可以写一个shell脚本,使用cmdline-jmxclient.jar工具实时的取到所有topic的流量,然后再做排序。这个方法比较繁琐,仍需考虑Topic的分区是否分布在不同的Broker上,是否需要做汇总等。

3. 如果不想用2的办法,有一个简单的办法可以大概看出流量的分布。先进入broker上的数据目录,然后查看每个分区的堆积的数据量大小。比如执行如下命令:ll -h /data/kafka_data/。根据堆积的情况来判断哪些Topic的流量相对较大。

当然,如果集群中所有主题的流量都非常平均,那就对所有的Topic一起处理。接下来我们来讨论下当遇到紧急扩容的需求时,有哪些方案可以选择。

以下方案的核心思想:迁移尽量少的数据,或者不迁移实现压力的转移

方案一:降低数据保留时间,精准迁移

这个方案是大家最常用的方法,也是操作起来最简单的。无论集群整体压力都高还是某些Broker的压力大,都可以通过这个方案来执行扩容。一般执行如下四步:

1. 找出需要操作的Topic

2. 调整这些Topic的数据保留时间

3. 对这些Topic进行迁移

4. 等待迁移完成,完成Leader切换,均分集群压力。

此时当整个集群压力都很大的时候,这个方案下最好的处理方式是:调整流量最大的分区的保留时间,然后针对每条broker迁移几个分区到新的节点上。比如,从每台Broker挑出3个分区,然后迁移到目标节点上。如果只有几台Broker压力大,也是一样的处理方式。

这种方式有两个缺点:

  1. 业务数据的保留时间不一定能调短,因为调短了数据保留时间,这些数据就会被删除,无法恢复。所以,当业务不允许删除数据的时候,这个方案就不允许使用。
  2. 当业务允许调整数据保留时间,比如调整到1个小时。此时还有一个小时的数据需要迁移,如果此时当前节点的负载已经很高了。此时副本拉取数据即会增加当前节点的负载,导致集群更加无法提供正常服务。当前节点压力大的话,可能导致新副本同步数据比较慢,会导致集群的压力没法快速降下来。

那有没有方案可以解决这个问题呢?我们再来看下一个方案。

方案二:往指定节点上添加分区,均分压力

如方案一所示,当整个集群压力都很大时,扩容节点后,因为数据迁移的方案无法使用,新节点无法承担压力,集群负载也降不下来。

此时可以通过扩容分区到新节点,将流量导到新的节点,让新的节点也可以承担流量。一般执行如下三步:

  • 找出需要操作的Topic
  • 评估这些Topic需要导多少流量到新节点。这一步比较好做,一般比如要把30%,50%的流量导入到新节点,大概评估一下即可。
  • 扩容目标Topic的分区数,将这些新增的分区指定扩容到新的节点上。

因为扩容Topic的目标分区是秒级完成的,所以不需要等待。在没有分区变更的情况下客户端的metadata机制默认是每隔30s自动更新一次,所以客户端会很快感知到分区变化,默认的生产者写入策略是轮询的,此时新增的流量会自动流入到新节点,原先的节点的负载很快就降下来了。

方案二的核心点:新增扩容分区,比如指定添加到目标节点。如果只是扩容分区,而这些分区还是落到老的节点上,是解决不了问题的。因为一般情况下Topic的分区的流量都是均匀的,假设Topic当前分区是100,想让新的节点承担该Topic 50%的压力,可以将该Topic的分区数扩容到200。如下图所示:

图片
图片

图4:分区扩容示意图

这种方式有如下几个缺点:

1. 如果业务逻辑限制了分区数不可变更,比如业务根据分区数做了哈希,根据哈希值往分区写数据,又需要要求数据保持有序。那么该方案就行不通了。但是一般情况下,有如上业务场景的Topic数据量都比较小,不会成为瓶颈Topic。反之,成为瓶颈的Topic,数据量都很大,一般都允许扩容分区。所以,这点通常情况下不会成为限制,但是在操作前最好和业务确认下。

2. 这种行为针对单个Topic不能多次使用。因为主题的分区一般不能删除,因为删除分区后,分区中的数据也会丢失。如果在单个Topic多次使用的策略下,该Topic的分区数就会膨胀到很大。比如每次都需要导出50%的流量,则需要再添加100个分区,此时总分区数量就需要为200。以此类推,则总分区数的变化趋势为:100,200,400,800,1600......。

3. 如果客户端写入有倾斜,即客户端指定了写入策略,只针对某些分区写入,现在的方案就会失效。遇到这种情况,只能协调客户端处理。

虽然这个方案有以上几个缺点,但是整体方案可以应对90%以上的紧急情况。所以,在不用迁移就降低集群负载的情况下,这个方案是很好用的。

方案三:切换Leader,降低单机负载

方案二比较适合整个集群负载较高的场景,或者因为某些头部Topic的流量均匀的集中在部分节点的情况下。现在我们来看一下如下场景:

假设集群有20台节点,节点的机型和规格是一样的,从网卡进出流量上来看,流量是均衡的。但是因为节点间性能的差异(原因可能是机型年限不一样,不同节点上Topic的业务形态不一样等等),导致某几台节点的负载很高。

此时,如果通过方案二处理,就会有种杀鸡用牛刀的感觉,而且效果并不好。为什么呢?

假设头部流量的Topic分区均匀分配在了20台节点上。如果要通过扩容分区降低其中几台的负载,因为生产端是均匀写入的,则需要扩容很多倍的分区到新的节点上,才能把这几台的流量降下来。这会导致该Topic的分区数急速膨胀。

在这种情况下,我们可以尝试切换分区 Leader的方案来降低单机的压力。这个操作比较简单,因为Leader切换的速度是秒级的,所以见效也很快。思路如下:

  1. 找出负载高的节点上的所有Leader
  2. 将节点上分区的Leader切换到负载较低的Follower节点上

这个操作的原理是:Kafka分区都在Leader进行读写,从单个分区看,即分区Leader所在节点的负载就会比Follower的节点负载高。所以,思路就是将负载高的节点上的Leader变为Fllower,降低单机压力,来看下图:

图片
图片

  图5:切换Leader前

图片
图片

  图6:切换Leader后

这种方式的缺点如下:

  • 这种方式适用于部分节点负载较高的情况,因为负载会转移到Follower上,如果Follower的负载本身就很高,则这种手段会加大Follower的压力。
  • 当Leader出现负载较高的时候,副本可能会掉出ISR。因为Leader负载高,Follower拉取数据慢,导致副本跟不上Leader,掉出ISR。当出现这种情况,就不能切换Leader,强行切换的话,会出现数据截断,导致数据丢失。

我们继续来看一下,有没有其他方法可以解决这种问题。

方案四:单副本运行,降低单机负载

当出现方案三中的无法处理的情况时,即无法使用切换Leader的手段降低压力时。我们可以通过将高负载节点上的分区Follower剔除,将分区切换为单副本运行,来临时降低节点的压力,让集群暂时的快速回归正常。

思路如下:

  1. 找出负载高节点上的所有Follower
  2. 将节点上的Follower暂时移除

这个操作的原理:分区的Follower会不断的从Leader同步数据,即从Leader拉取数据到本地进行报错。这个行为会占用CPU,网卡,磁盘等资源,如果把这一部分流量去掉,则会把节点上这部分负载空出来。能快速地降低节点压力。

图片
图片

图7: 切掉Follower前

图片
图片

图8: 切掉Follower后

这种方式的缺点:切掉Follower后,分区就是单副本运行,没有备份。如果这台节点挂了,那服务就会出现异常,可能出现数据写入异常。

这个步骤还有一个执行风险:切掉Follower,节点负载降低后,一定要记得把停掉分区分区的Follower重新启动,否则单副本运行的数据,没有备份,很容易出现故障。

图片
图片

图9:  在其他节点拉起Follower

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是数据迁移
  • 扩容场景:
  • 找到Top主题
  • 那怎么样找到Top主题呢?
  • 以下方案的核心思想:迁移尽量少的数据,或者不迁移实现压力的转移。
    • 方案一:降低数据保留时间,精准迁移
      • 方案二:往指定节点上添加分区,均分压力
        • 方案三:切换Leader,降低单机负载
          • 方案四:单副本运行,降低单机负载
          相关产品与服务
          消息队列 CKafka 版
          消息队列 CKafka 版(TDMQ for CKafka)是一个分布式、高吞吐量、高可扩展性的消息系统,100%兼容开源 Kafka API 2.4、2.8、3.2 版本。CKafka 基于发布/订阅模式,通过消息解耦,使生产者和消费者异步交互,无需彼此等待。CKafka 具有高可用、数据压缩、同时支持离线和实时数据处理等优点,适用于日志压缩收集、监控数据聚合、流式数据集成等场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档