是否可以将分区添加到 Kafka 0.8.2 中的现有主题

Posted

技术标签:

【中文标题】是否可以将分区添加到 Kafka 0.8.2 中的现有主题【英文标题】:Is it possible to add partitions to an existing topic in Kafka 0.8.2 【发布时间】:2016-02-14 03:45:50 【问题描述】:

我有一个运行 2 个分区的 Kafka 集群。我正在寻找一种将分区数增加到 3 的方法。但是,我不想丢失有关该主题的现有消息。我尝试停止Kafka,修改server.properties文件将分区数增加到3并重新启动Kafka。然而,这似乎并没有改变什么。使用 Kafka ConsumerOffsetChecker,我仍然看到它只使用了 2 个分区。我使用的Kafka 版本是0.8.2.2。在 0.8.1 版中,曾经有一个名为kafka-add-partitions.sh 的脚本,我想这可能会奏效。但是,我在 0.8.2 中没有看到任何这样的脚本。

有没有办法做到这一点?

我确实尝试过创建一个全新的主题,对于那个主题,它似乎确实根据server.properties 文件中的更改使用了 3 个分区。但是,对于现有的主题,它似乎并不在意。

【问题讨论】:

apache kafka 的最新版本是 0.8.2.2,我怀疑你使用的是“2.10”。您可能需要再次检查版本。 @C4stor 实际上我的意思是基于 Scala 2.10 的 Kafka,这正是你提到的 0.8.2.2 版本。对困惑感到抱歉。我将编辑我的问题。 【参考方案1】:

我觉得这个问题有点老了,但我还是会回答。

如果您有一个 Kafka 主题但想要更改分区或副本的数量,您可以使用流式转换将所有消息从原始主题自动流式传输到具有所需分区或副本数量的新 Kafka 主题.

【讨论】:

【参考方案2】:

如果您在 Windows 中使用 Kafka 尝试使用此代码更改或在主题中添加分区

.\bin\windows\kafka-topics.bat --alter --zookeeper localhost:2181 --topic TopicName --partitions 20

.\bin\windows\kafka-topics.bat --alter --zookeeper localhost:2181 --topic TopicName --replica-assignment 0:1:2,0:1:2,0:1:2,2:1:0 --partitions 10

【讨论】:

【参考方案3】:

对于任何想要更新 Kafka 版本的解决方案的人。请遵循此方法。

Kafka 的整个数据保留和传输策略取决于分区,因此请注意增加分区的影响。 (Kafka 的较新版本会对此显示警告)尽量避免一个代理有太多领导分区的配置。

有一个简单的 3 阶段方法。

第一步:增加主题的分区

./bin/kafka-topics.sh --zookeeper localhost:9092 --alter --topic testKafka_5 --partitions 6

第 2 步:为给定主题创建分区 json 文件

“版本”:1,“分区”:[ "topic":"testKafka_5","partition":0,"replicas":[0,1,2], "topic":"testKafka_5","partition":1,"replicas":[2,1,0], "topic":"testKafka_5","partition":2,"replicas":[1, 2,0], "topic":"testKafka_5","partition":3,"replicas":[0,1,2], "topic":"testKafka_5","partition":4,"replicas":[2,1,0], "topic":"testKafka_5","partition":5,"replicas":[1, 2,0] ]

使用更新的分区和副本创建文件。最好将副本扩展到不同的代理,但它们应该存在于同一个集群中。考虑远程副本的延迟。 将给定文件传输到您的 Kafka。

第 3 步:重新分配分区并验证

./bin/kafka-reassign-partitions.sh --zookeeper localhost:9092 --reassignment-json-file bin/increase-replication-factor.json  --execute

./bin/kafka-reassign-partitions.sh --zookeeper localhost:9092 --reassignment-json-file bin/increase-replication-factor.json --verify

您可以使用 --describe 命令检查更改的效果。

【讨论】:

【参考方案4】:

在我的情况下,参数--zookeeper 的值zk_host:port/chroot 引发了以下异常:

错误 java.lang.IllegalArgumentException:主题 my_topic_name 不存在于 ZK 路径 zk_host:port/chroot 上。

所以,我尝试了以下方法并且成功了:

 bin/kafka-topics.sh --alter --zookeeper zk_host:port --topic my_topic_name --partitions 10

【讨论】:

chroot 是一个可选的配置设置,不是字面意思 只需确保所有复制集/代理都已启动。否则会抛出这个错误:RROR org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 2 large than available brokers: 1.【参考方案5】:

看来您可以改用this 脚本:

bin/kafka-topics.sh --zookeeper zk_host:port/chroot --alter --topic my_topic_name 
   --partitions 40 

在代码中看起来他们做同样的事情:

 AdminUtils.createOrUpdateTopicPartitionAssignmentPathInZK(topic, partitionReplicaList, zkClient, true)

kafka-topics.sh 执行 this 一段代码以及 kafka-add-partition 脚本使用的 AddPartitionsCommand。

但是你必须注意在使用密钥时重新分区:

请注意,分区的一种用例是语义分区 数据,并且添加分区不会更改现有数据的分区,因此如果消费者依赖该数据,这可能会打扰消费者 划分。也就是说,如果数据被hash(key) % number_of_partitions 分区,那么这个分区可能是 通过添加分区进行改组,但 Kafka 不会尝试 以任何方式自动重新分配数据。

【讨论】:

如果数据必须重新分区,有没有办法只移动未读消息而忽略已读消息? 符合“仅附加”理念,我想您必须竭尽全力才能实现这一目标。我想说最简单的是停止对该主题的消费,创建一个具有所需分区数量的新主题,将未读消息重新发布到新主题,然后继续消费新主题。 @CmdrDats,如果这方面有任何改进,请告诉我,或者我们仍然使用您上面建议的“重新发布”方法来解决这个问题。

以上是关于是否可以将分区添加到 Kafka 0.8.2 中的现有主题的主要内容,如果未能解决你的问题,请参考以下文章

如何将消息发送到 Kafka 中的特定分区?

kafka-python KafkaConsumer 多分区提交偏移量

Kafka集群管理工具kafka-manager安装使用

Kafka 消费者是否可以消费指定分区消息?

Kafka 消费者是否可以消费指定分区消息?

Kafka分区与消费者的关系