KafkaProducer 循环分配不适用于同一个密钥

KafkaProducer round-robin distribution not working for the same key

我正在尝试了解 Kafka 的工作原理。我读过,默认情况下,Kafka 会在分区之间以循环方式分发来自生产者的消息。

但是,如果消息具有相同的密钥,为什么消息总是放在同一个分区中? (没有配置分区键策略)。

例如,使用下面的代码,消息总是放在同一个分区中:

KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
String key = properties.getProperty("dev.id");
producer.send(new ProducerRecord<String, String>(properties.getProperty("kafka.topic"), key, value), new EventGeneratorCallback(key));

使用不同的密钥,消息以循环方式分发:

KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
String key = properties.getProperty("dev.id") + UUID.randomUUID().toString();
producer.send(new ProducerRecord<String, String>(properties.getProperty("kafka.topic"), key, value), new EventGeneratorCallback(key));

这是预期的行为。所有具有相同密钥的消息都放在同一个分区中。如果您希望对所有消息进行循环分配,则不应提供密钥。对 Kafka 来说,拥有密钥的原因是在整个分区中分布数据,将相同的密钥放在不同的分区中会破坏这个契约。

这正是 Kafka 生产者的工作方式。此行为由 DefaultPartitioner class 定义,您可以在官方仓库中找到 here。 如果未指定密钥,则生产者使用循环方式在所有与主题相关的分区之间发送消息;如果指定了密钥,则分区程序会处理密钥模块的哈希值和分区数,这样具有相同密钥的消息就会进入同一分区。因为 Kafka 保证在分区级别(而不是主题级别)排序,这也是一种让所有消息在同一个分区中具有相同键的方式,因此消费者按照它们发送的顺序接收。 最后,另一种发送消息的可能方式是生产者指定分区目的地:在这种情况下没有密钥,没有循环但消息被准确地发送到生产者自己指定的分区。