分区重分配

当集群中的一个节点突然宕机下线时,如果节点上的分区是单副本的,那么这些分区就变得不可用了,在节点恢复前,相应的数据也就处于丢失状态;如果节点上的分区是多副本的,那么位于这个节点上的 leader 副本的角色会转交到集群的其他 follower 副本中。总而言之,这个节点上的分区副本都已经处于功能失效的状态,Kafka 并不会将这些失效的分区副本自动地迁移到集群中剩余的可用 broker 节点上,如果放任不管,则不仅会影响整个集群的均衡负载,还会影响整体服务的可用性和可靠性。

当要对集群中的一个节点进行有计划的下线操作时,为了保证分区及副本的合理分配,我们也希望通过某种方式能够将该节点上的分区副本迁移到其他的可用节点上。

当集群中新增 broker 节点时,只有新创建的主题分区才有可能被分配到这个节点上,而之前的主题分区并不会自动分配到新加入的节点中,因为在它们被创建时还没有这个新节点,这样新节点的负载和原先节点的负载之间严重不均衡。

为了解决上述问题,需要让分区副本再次进行合理的分配,也就是所谓的分区重分配。Kafka 提供了 kafka-reassign-partitions.sh 脚本来执行分区重分配的工作,它可以在集群扩容、broker 节点失效的场景下对分区进行迁移。 kafka-reassign-partitions.sh 脚本的使用分为3个步骤:首先创建需要一个包含主题清单的 JSON 文件,其次根据主题清单和 broker 节点清单生成一份重分配方案,最后根据这份方案执行具体的重分配动作。

下面我们通过一个具体的案例来演示 kafka-reassign-partitions.sh 脚本的用法。首先在一个由3个节点(broker 0、broker 1、broker 2)组成的集群中创建一个主题 topic-reassign,主题中包含4个分区和2个副本:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/ kafka --create --topic topic-reassign --replication-factor 2 --partitions 4
Created topic "topic-reassign".[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/ kafka --describe --topic topic-reassign
Topic:topic-reassign    PartitionCount:4    ReplicationFactor:2 Configs: Topic: topic-reassign  Partition: 0    Leader: 0   Replicas: 0,2   Isr: 0,2Topic: topic-reassign   Partition: 1    Leader: 1   Replicas: 1,0   Isr: 1,0Topic: topic-reassign   Partition: 2    Leader: 2   Replicas: 2,1   Isr: 2,1Topic: topic-reassign   Partition: 3    Leader: 0   Replicas: 0,1   Isr: 0,1

我们可以观察到主题 topic-reassign 在3个节点中都有相应的分区副本分布。由于某种原因,我们想要下线 brokerId 为1的 broker 节点,在此之前,我们要做的就是将其上的分区副本迁移出去。使用 kafka-reassign-partitions.sh 脚本的第一步就是要创建一个 JSON 文件(文件的名称假定为 reassign.json),文件内容为要进行分区重分配的主题清单。对主题 topic-reassign 而言,示例如下:

{"topics":[{"topic":"topic-reassign"}],"version":1
}

第二步就是根据这个 JSON 文件和指定所要分配的 broker 节点列表来生成一份候选的重分配方案,具体内容参考如下:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-reassign-partitions.sh --zookeeper localhost:2181/kafka --generate --topics-to-move-json-file reassign.json --broker-list 0,2
Current partition replica assignment
{"version":1,"partitions":[{"topic":"topic-reassign","partition":2,"replicas":[2,1],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":1,"replicas":[1,0],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":3,"replicas":[0,1],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":0,"replicas":[0,2],"log_dirs":["any","any"]}]}Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"topic-reassign","partition":2,"replicas":[2,0],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":1,"replicas":[0,2],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":3,"replicas":[0,2],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":0,"replicas":[2,0],"log_dirs":["any","any"]}]}

上面的示例中包含4个参数,其中 zookeeper 已经很常见了,用来指定 ZooKeeper 的地址。generate 是 kafka-reassign-partitions.sh 脚本中指令类型的参数,可以类比于 kafka-topics.sh 脚本中的 create、list 等,它用来生成一个重分配的候选方案。topic-to-move-json 用来指定分区重分配对应的主题清单文件的路径,该清单文件的具体的格式可以归纳为{"topics": [{"topic": "foo"},{"topic": "foo1"}],"version": 1}。broker-list 用来指定所要分配的 broker 节点列表,比如示例中的“0,2”。

上面示例中打印出了两个 JSON 格式的内容。第一个“Current partition replica assignment”所对应的 JSON 内容为当前的分区副本分配情况,在执行分区重分配的时候最好将这个内容保存起来,以备后续的回滚操作。第二个“Proposed partition reassignment configuration”所对应的 JSON 内容为重分配的候选方案,注意这里只是生成一份可行性的方案,并没有真正执行重分配的动作。生成的可行性方案的具体算法和创建主题时的一样,这里也包含了机架信息,具体的细节可以参考17节的内容。

我们需要将第二个 JSON 内容保存在一个 JSON 文件中,假定这个文件的名称为 project.json。

第三步执行具体的重分配动作,详细参考如下:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-reassign-partitions.sh --zookeeper localhost:2181/kafka --execute --reassignment-json-file project.json
Current partition replica assignment{"version":1,"partitions":[{"topic":"topic-reassign","partition":2,"replicas":[2,1],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":1,"replicas":[1,0],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":3,"replicas":[0,1],"log_dirs":["any","any"]},{"topic":"topic-reassign","partition":0,"replicas":[0,2],"log_dirs":["any","any"]}]}Save this to use as the --reassignment-json-file option during rollback
Successfully started reassignment of partitions.

我们再次查看主题 topic-reassign 的具体信息:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/ kafka --describe --topic topic-reassign
Topic:topic-reassign    PartitionCount:4    ReplicationFactor:2 Configs: Topic: topic-reassign  Partition: 0    Leader: 0   Replicas: 2,0   Isr: 0,2Topic: topic-reassign   Partition: 1    Leader: 0   Replicas: 0,2   Isr: 0,2Topic: topic-reassign   Partition: 2    Leader: 2   Replicas: 2,0   Isr: 2,0Topic: topic-reassign   Partition: 3    Leader: 0   Replicas: 0,2   Isr: 0,2

可以看到主题中的所有分区副本都只在0和2的 broker 节点上分布了。

在第三步的操作中又多了2个参数,execute 也是指令类型的参数,用来指定执行重分配的动作。reassignment-json-file 指定分区重分配方案的文件路径,对应于示例中的 project.json 文件。

除了让脚本自动生成候选方案,用户还可以自定义重分配方案,这样也就不需要执行第一步和第二步的操作了。

分区重分配的基本原理是先通过控制器为每个分区添加新副本(增加副本因子),新的副本将从分区的 leader 副本那里复制所有的数据。根据分区的大小不同,复制过程可能需要花一些时间,因为数据是通过网络复制到新副本上的。在复制完成之后,控制器将旧副本从副本清单里移除(恢复为原先的副本因子数)。注意在重分配的过程中要确保有足够的空间。

细心的读者可能观察到主题 topic-reassign 中有3个 leader 副本在 broker 0 上,而只有1个 leader 副本在 broker 2 上,这样负载就不均衡了。不过我们可以借助上一节中的 kafka-perferred-replica-election.sh 脚本来执行一次优先副本的选举动作,之后可以看到主题 topic-reassign 的具体信息已经趋于完美:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/ kafka --describe --topic topic-reassign
Topic:topic-reassign    PartitionCount:4    ReplicationFactor:2 Configs: Topic: topic-reassign  Partition: 0    Leader: 2   Replicas: 2,0   Isr: 0,2Topic: topic-reassign   Partition: 1    Leader: 0   Replicas: 0,2   Isr: 0,2Topic: topic-reassign   Partition: 2    Leader: 2   Replicas: 2,0   Isr: 2,0Topic: topic-reassign   Partition: 3    Leader: 0   Replicas: 0,2   Isr: 0,2

对于分区重分配而言,这里还有可选的第四步操作,即验证查看分区重分配的进度。只需将上面的 execute 替换为 verify 即可,具体示例如下:

[root@node1 kafka_2.11-2.0.0]# bin/kafka-reassign-partitions.sh --zookeeper localhost:2181/kafka --verify --reassignment-json-file project.json
Status of partition reassignment:
Reassignment of partition topic-reassign-2 completed successfully
Reassignment of partition topic-reassign-1 completed successfully
Reassignment of partition topic-reassign-3 completed successfully
Reassignment of partition topic-reassign-0 completed successfully

分区重分配对集群的性能有很大的影响,需要占用额外的资源,比如网络和磁盘。在实际操作中,我们将降低重分配的粒度,分成多个小批次来执行,以此来将负面的影响降到最低,这一点和优先副本的选举有异曲同工之妙。 还需要注意的是,如果要将某个 broker 下线,那么在执行分区重分配动作之前最好先关闭或重启 broker。这样这个 broker 就不再是任何分区的 leader 节点了,它的分区就可以被分配给集群中的其他 broker。这样可以减少 broker 间的流量复制,以此提升重分配的性能,以及减少对集群的影响。

分区重分配(二十二)相关推荐

  1. 2021年大数据Hadoop(二十二):MapReduce的自定义分组

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 MapReduce的自定义分组 需求 分析 实现 第一步: ...

  2. 一位中科院自动化所博士毕业论文的致谢:二十二载风雨求学路,他把自己活成了光.........

    4月18日,中国科学院官方微博发布消息,披露了这篇论文为<人机交互式机器翻译方法研究与实现>,作者是2017年毕业于中国科学院大学的工学博士黄国平. 这篇论文中情感真挚的<致谢> ...

  3. iOS 11开发教程(二十二)iOS11应用视图实现按钮的响应(2)

    iOS 11开发教程(二十二)iOS11应用视图实现按钮的响应(2) 此时,当用户轻拍按钮后,一个叫tapButton()的方法就会被触发. 注意:以上这一种方式是动作声明和关联一起进行的,还有一种先 ...

  4. 实验二十二 SCVMM中的SQL Server配置文件

    实验二十二 SCVMM中的SQL Server配置文件 在VMM 2012中管理员可以使用 SQL Server 配置文件,在部署完成虚拟机之后,实现 SQL Server 数据库服务自动化部署并交付 ...

  5. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  6. OpenCV学习笔记(二十一)——绘图函数core OpenCV学习笔记(二十二)——粒子滤波跟踪方法 OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt OpenCV学习笔记(二十

    OpenCV学习笔记(二十一)--绘图函数core 在图像中,我们经常想要在图像中做一些标识记号,这就需要绘图函数.OpenCV虽然没有太优秀的GUI,但在绘图方面还是做得很完整的.这里就介绍一下相关 ...

  7. 读书二十二载,信念很简单,把书念下去,然后走出去,不枉活一世。

    ‍ ‍ 关注+星标公众号,不错过精彩内容 昨天看了一篇关于博士论文的致谢,看的我想哭.改变命运有很多条路,但是对于大多数人而言,读书是改变命运的捷径. 内容是讲述了自己20多年的求学经历:小时候煤油灯 ...

  8. (原创)无废话C#设计模式之二十二:总结(针对GOF23)

    无废话C#设计模式之二十二:总结(针对GOF23) 比较 设计模式 常用程度 适用层次 引入时机 结构复杂度 Abstract Factory 比较常用 应用级 设计时 比较复杂 Builder 一般 ...

  9. Android项目实战(二十二):启动另一个APP or 重启本APP

    Android项目实战(二十二):启动另一个APP or 重启本APP 原文:Android项目实战(二十二):启动另一个APP or 重启本APP 一.启动另一个APP 目前公司项目需求,一个主AP ...

  10. FreeSql (二十二)Dto 映射查询

    适合喜欢使用 dto 的朋友,很多时候 entity 与 dto 属性名相同,属性数据又不完全一致. 有的人先查回所有字段数据,再使用 AutoMapper 映射. 我们的功能是先映射,再只查询映射好 ...

最新文章

  1. Java 面试高频题:Spring Boot+Sentinel+Nacos高并发已撸完
  2. codeforces Palindromic characteristics(hash或者dp)
  3. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)
  4. ADO.NET+Access: 3,参数 @departmentName 没有默认值
  5. Angle Admin Template介绍
  6. 为什么 jmeter 分布式测试,一定要设置 java.rmi.server.hostname
  7. How to Become a Better Learner
  8. h5 bootstrap 小程序模板_教你获取小程序码或小程序H5页面路径
  9. 苹果怎么修改wifi代理服务器,苹果手机怎么修改wifi名称?
  10. jvm核心技术梳理(持续更新)
  11. 服务器如何挂网页游戏,网页游戏怎么挂云服务器
  12. 富文本 和 图片裁切
  13. Django学习记录之——csrf跨站请求伪造校验
  14. unity摄影机depth模式_Unity3d摄像机详解
  15. 电脑本机使用手机热点、虚拟机如何联网
  16. 调用批处理bat文件
  17. 0902 团队销售漏斗
  18. npm publish 发包报错400 Bad Request - Cannot publish over previously published version 1.0.0
  19. 赛龙代小权终审无罪释放,重燃创业之心
  20. 为何某些文章的阅读量这么高?

热门文章

  1. 『进出口贸易』 [经验交流]外贸朋友们一定进来看看,关于贸易成本核算问题(做人要厚道)
  2. 费舍尔精确检验在关联分析中的应用
  3. LeetCode500. 键盘行
  4. 宋词欣赏 -- 李清照词全集
  5. 如何装虚拟机及在上面安装LINUX操作系统
  6. matlab之常用命令整理(持续更新中...)
  7. 语音处理:PCM文件中采样值到dB分贝的转换分析
  8. 亚马逊云科技 + 英特尔 + 中科创达为行业客户构建 AIoT 平台
  9. Python Cerberus
  10. 8086寄存器学习笔记-SS 寄存器和 SP 寄存器