我遇到了有关Kafka重新平衡的奇怪事情。如果我增加某个Java使用者(在同一组中)订阅的主题的分区,则不会发生使用者重新平衡。之后,我尝试通过启动新使用者(或杀死一个使用者)来引起重新平衡,并且无法在此重新平衡中分配新增加的分区。我发现只有在停止所有使用者并启动它们之后才能分配新分区。我不知道这是正常现象还是对此有任何解释。
以下是我在计算机上进行的测试:
1。启动ZK卡夫卡。创建一个具有1个分区的普通主题( test-topic )
./bin/kafka-topics.sh --zookeeper 127.0.0.1:2181 --create --topic test-topic --partitions 1 --replication-factor 1 --config retention.ms=604800000
2。启动2个Java使用者( C1 , C2 ),订阅 test-topic
3。增加2个 test-topic
分区$ ./bin/kafka-topics.sh --zookeeper 127.0.0.1:2181 --alter --topic test-topic --partitions 3
C1 , C2
中没有发生重新平衡4。启动新的使用者 C3 以订阅测试主题。发生重新平衡,但仅涉及重新分配的分区 test-topic-0 ,没有涉及 test-topic-1 或 test-topic-2 。
5。我尝试通过停止 C2 和 C3 来引起重新平衡。但是 test-topic-1 和 test-topic-2 仍未分配。
6。停止所有正在运行的使用者,然后启动它们。所有 test-topic-0,1,2 均已正常分配。
kafka和java api版本:kafka_2.12-2.0.0(我也尝试过kafka_2.11-1.0.0和kafka_2.10-0.10.2.1,结果相同)
动物园管理员:3.4.13
消费者代码:
public class KafkaConsumerThread extends Thread {
// consumer settings
public static org.apache.kafka.clients.consumer.KafkaConsumer<String, String> createNativeConsumer(String groupName, String kafkaBootstrap) {
Properties props = new Properties();
props.put("bootstrap.servers", kafkaBootstrap);
props.put("group.id", groupName);
props.put("auto.offset.reset", "earliest");
props.put("enable.auto.commit", true);
props.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
return new KafkaConsumer<String, String>(props);
}
@Override
public void run() {
log.info("Start consumer ..");
consumer.subscribe(Collections.singleton(topicName), consumerRebalanceListener);
while (!stop) {
try {
ConsumerRecords<String, String> records = consumer.poll(100);
receivedRecordNumber.addAndGet(records.count());
Iterator<ConsumerRecord<String, String>> iterator = records.iterator();
while (iterator.hasNext()) {
ConsumerRecord<String, String> record = iterator.next();
log.info("Receive [key:{}][value:{}]", record.key(), record.value());
}
} catch (TimeoutException e) {
log.info("no data");
}
}
consumer.close();
}
}
感谢@Aftab Virtual的评论。我再次测试,等待更长的时间。第一个使用者启动约5分钟后,自动重新分配平衡,并重新分配了所有分区 test-topic-0,1,2 。因此,更改分区后,Kafka确实具有自动重新平衡的功能。
此外,我遵循@Aftab Virtual的建议将leader.imbalance.check.interval.seconds
更改为30。但是,重新平衡涉及的所有分区都在分区增加后约3分钟发生。我确实为代理添加了设置:
auto.leader.rebalance.enable = true
leader.imbalance.check.interval.seconds = 30
我不知道这种重新平衡的机制是什么。而且没有更多的日志可用于这种重新平衡:
[2018-10-18 11:32:47,958] INFO [GroupCoordinator 0]: Preparing to rebalance group test-group with old generation 4 (__consumer_offsets-12) (kafka.coordinator.group.GroupCoordinator)
[2018-10-18 11:32:50,963] INFO [GroupCoordinator 0]: Stabilized group test-group generation 5 (__consumer_offsets-12) (kafka.coordinator.group.GroupCoordinator)
[2018-10-18 11:32:50,964] INFO [GroupCoordinator 0]: Assignment received from leader for group test-group for generation 5 (kafka.coordinator.group.GroupCoordinator)
答案 0 :(得分:0)
在征求Kafka团队和一些Kafka用户的建议后,我得到了测试结果的解释。这不是错误。
分区的增加将标记为metadata.updateNeeded = true。但是,这不会真正触发更新,直到下一个元数据到期时间为止(默认metadata.max.age.ms
为5 * 60 * 1000 ms)。在组长更新其元数据之前,由更改消费者编号引起的重新平衡将不涉及新分区。
我将metadata.max.age.ms
减少到30秒,Kafka对分区增加变得更加敏感。