消费者之间的kafka消息分发

时间:2019-03-01 20:05:12

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

我有一个非常简单的kafka用例,其中我面临着2个分区之间的消息分发问题。

我在主题上有2个分区,每个都有2个使用者。我可以看到有更多消息发送到特定分区,并且只有一个使用者正在处理消息,而另一个订阅了较少消息的分区永远处于空闲状态。两个使用者的群组ID相同。我无法通过此问题实现水平缩放。

下面是我要放置的关键配置。

kafka.session.timeout.ms=10000
kafka.auto.commit=false
kafka.maxpoll.interval.ms=50000
kafka.request.timeout.ms=15000
kafka.maxpoll.records=100

** PS:**名称来自我的prop文件,与真实的kafka属性名称不完全匹配。 我需要较大的最大轮询间隔,以便一次性处理较大的块。我需要在配置中添加或更改它的任何猜测吗?

2 个答案:

答案 0 :(得分:0)

Kafka生产者:生产者根据记录的密钥将记录发送到分区。 Java的默认分区程序使用记录键的哈希值来选择分区,如果记录没有键,则使用循环策略。因此,要获得更大的可伸缩性,请始终对消息使用唯一键

  

生产者将数据发布到他们选择的主题。生产者负责选择将哪个记录分配给主题中的哪个分区。 这可以循环方式完成,仅用于平衡负载,也可以根据某些语义分区功能(例如基于记录中的某些键)完成。一秒钟就能了解更多有关分区的使用!

如果记录具有相同的键,那么它们将在相同的分区中结束

您还可以将记录发送到特定分区

public ProducerRecord(String topic,
          Integer partition,
          K key,
          V value)
  

创建要发送到指定主题和分区的记录

答案 1 :(得分:0)

如其他答案所述,kafka使用键的哈希值来确定分区。可能是您的密钥分布不均匀。在这种情况下,您可以定义自己的策略以在生成记录时按生产者选择分区。 创建一个自定义partitoner类,并实现其分区方法,如下所示。

import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.record.InvalidRecordException;

public class CustomPartitioner implements Partitioner {

    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
        int numPartitions = partitions.size();
        if ((keyBytes == null) || (!(key instanceof String)))
            throw new InvalidRecordException("We expect all messages to have a key");
        // Your logic to decide partition based on key
        return 0;// Here return thr partition decided based on key
    }

    public void close() {
    }

    public void configure(Map<String, ?> configs) {
        // TODO Auto-generated method stub

    }
}

在生产者配置上,添加以下内容

properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, CustomPartitioner.class.getCanonicalName());
property