【问题标题】:Apache Kafka Partitions not evenly Distributed with RoundRobin PartitionerApache Kafka 分区未使用 RoundRobin Partitioner 均匀分布
【发布时间】:2022-04-02 17:41:19
【问题描述】:

我正在使用带有 RoundRobin 分区器的 Kafka Producer 来处理一个有 12 个分区的主题。

代码可以在这里找到 https://github.com/apache/kafka/blob/2.8/clients/src/main/java/org/apache/kafka/clients/producer/RoundRobinPartitioner.java

我面临的问题是这个分区器正在让分区正确发送特定消息(以循环方式)但在 kafka 生产者代码中,分区方法在第 931 和 956 行被调用两次(在新批次的 if 块内)由于某些分区没有记录发送给它们,我无法实现我想要的 12 的并行性。我已经尝试过以下事情。我已经使用与 roundrobin partitioner 相同的逻辑有效地编写了一个自定义分区器,唯一的区别是如果在分区器上调用 newBatch 方法之后调用分区方法,则返回先前返回的分区号。我有点紧张在生产中使用它而不理解为什么 kafka 生产者代码是上面指定的方式,如果有人可以对此有所了解,我将不胜感激。另外,如果有人有任何建议可以确保记录在每个分区上均匀分布,我也愿意接受。

卡夫卡生产者代码 - https://github.com/apache/kafka/blob/2.8/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java

提前谢谢你。

【问题讨论】:

    标签: java apache-kafka kafka-producer-api


    【解决方案1】:

    解决方案

    您应该使用DefaultPartitioner 而不是RoundRobinPartitioner

    对 DefaultPartitioner.java 的评论说:

    默认分区策略:

  • 如果记录中指定了分区,则使用它
  • 如果未指定分区但存在键,则根据键的散列选择分区
  • 如果不存在分区或键,请选择在批处理已满时更改的粘性分区。

    有关粘性分区的详细信息,请参阅 KIP-480。

  • 不为您的生产者记录提供指定的分区号或分区键,然后粘性分区将起作用,这大致使您的 Kafka 分区上的记录均匀。见Tip #2: Learn about the new sticky partitioner in the producer API

    内部

    再次,我想解释一下为什么 RoundRobinPartitioner 总是不能以通常假定的循环方式工作。 RoundRobinPartitioner中的“partition()”只能保证调用partition()方法的数量分布是循环的,不足以保证我们在partition上的记录是偶数的。

    注意KafkaProducer.doSend()partition()的调用很奇怪(可能连续两次调用partition())。

    当分区数为偶数时,此处的细微代码可能会导致分区分配不均。 假设我们有 4 个分区(0,1,2,3)和 8 条记录。

    record 1 -> 2 **partition()** call(return 0, return 1), finally assigned to partition 1
    record 2 -> 2 **partition()** call(return 2, return 3), finally assigned to partition 3
    record 3 -> 2 **partition()** call(return 0, return 1), finally assigned to partition 1
    record 4 -> 2 **partition()** call(return 2, return 3), finally assigned to partition 3
    record 5 -> 2 **partition()** call(return 0, return 1), finally assigned to partition 1
    ....
    

    看到了吗?记录只会分发到分区 1 和 3!

    结论

    RoundRobinPartitioner 有一个令人困惑的名字,它提供调用 partition() 的 RoundRobin,而不是 KafkaProducer.send() 的 RoundRobin。 为确保记录在所有分区中均匀分布,请使用 DefaultPartitioner

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-21
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 2012-07-10
      • 2011-04-04
      • 2013-01-05
      相关资源
      最近更新 更多