Java 对卡夫卡中的每条消息使用不同的键

Java 对卡夫卡中的每条消息使用不同的键,java,apache-kafka,kafka-producer-api,Java,Apache Kafka,Kafka Producer Api,我们在Java中有一个kafka生产者-消费者设置(使用spring kafka,但可能与此无关)。使用的键是String,值是CustomPOJO。生产者-消费者通过具有16个分区的单个主题测试主题进行通信。使用者的并发性为16,因此它可以并行地从每个分区读取数据 从文档和其他参考资料中,我了解到-使用null键将以循环方式在分区中分发发布者发送的消息。如果我对将消息分发到使用键派生的特定分区感兴趣,建议使用非空键 我在这里有以下疑问- 当前,生产者为每条消息发送唯一密钥。由于每条消息都是唯一

我们在Java中有一个kafka生产者-消费者设置(使用spring kafka,但可能与此无关)。使用的键是
String
,值是CustomPOJO。生产者-消费者通过具有16个分区的单个主题
测试主题
进行通信。使用者的并发性为16,因此它可以并行地从每个分区读取数据

从文档和其他参考资料中,我了解到-使用
null
键将以循环方式在分区中分发发布者发送的消息。如果我对将消息分发到使用键派生的特定分区感兴趣,建议使用非空键

我在这里有以下疑问-

  • 当前,生产者为每条消息发送唯一密钥。由于每条消息都是唯一的
    字符串
    ,因此在几乎所有情况下,它也会生成唯一的hashcode。消息将如何在这里分发,是像
    null
    键那样的循环,还是重复使用分区或任何其他控制机制的一些哈希逻辑
  • null
    键上使用上述策略的键是否有任何利弊
  • 我不需要维护消息的顺序或分组。在这种情况下,使用
    null
    键是明智的,还是每个消息都有一个唯一或非唯一的非null键仍然很好,如果是,为什么
  • 消费者正在分批阅读信息。具有或不具有关键影响批读取是否与单个读取不同
  • 客户端控制将消息发布到哪个分区。这个可以 可以随机完成,实现一种随机负载平衡,或者 可以通过一些语义划分函数来完成。我们揭露了真相 通过允许用户指定 键进行分区,并使用它对分区进行散列(有 如果需要,还可以选择覆盖分区函数)

    该键用于将消息拆分到不同的分区。根据我的经验,如果使用空键,它们将在分区0中结束

    空键不是一个好的设计选择,不应该在生产中使用。也许只是为了快速原型

    粘性分区策略 sticky partitioner通过选择一个分区来发送所有未设置密钥的记录,从而解决了将没有密钥的记录分散到较小批次的问题

    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster,
                         int numPartitions) {
        if (keyBytes == null) {
            return stickyPartitionCache.partition(topic, cluster);
        }
    

    如果指定键,默认情况下,将根据分区数的键模散列(
    散列(键)%partitions\u number
    )选择分区。通过使用唯一的密钥,您可以按分区均匀分布消息。您还可以通过向自定义分区器提供所需的逻辑来覆盖分区行为


    根据您的描述,您不需要密钥,在这种情况下,使用
    null
    ,它将略微:1)节省Kafka群集上的资源(不要存储不需要的密钥),2)减少网络延迟,3)应用程序不会生成唯一密钥,也不会从中计算哈希(如果您有密钥,所有这些点都是次要的,相比之下并不重要)。如果您希望对具有相同密钥的消息进行排序,则应使用密钥(但这不是您的情况,因为您有唯一的密钥),或者您有基于此键的业务逻辑。批处理可以与
    null
    键一起正常工作。

    Kafka producer基于DefaultPartitioner、custom partitioner向特定分区发送消息,或者在发送消息以获得对特定分区的写入时传递分区信息。 定义为null或NOTNULL的键基于您的用例和需求,但其主要目的是将您的消息分布在不同的分区上,以供消费者组的多个消费者使用

    非null键确保相似的键将停在同一分区上,这将帮助您将多个相似的键分组到同一个bucket上,以便进一步分析,同时null键使您均匀地分发消息

    非null键始终有助于传递消息的元详细信息以供进一步处理。我更喜欢使用自定义分区器传递非null键以控制消息流。但这取决于具体要求,如果您想传递null键,这是绝对正确的

    注意:在未来版本ApacheKafka(2.5)中,您可以定义 作为分区策略的循环分区器(KIP-369),不需要 将该键设置为null。

  • 如果未定义自定义分区器,则将使用默认分区器
  • 在ApacheKafka2.4之前,它将经历一个又一个循环,并将记录发送给每个循环。 在本例中,ApacheKafka2.4之前的旧分区策略是循环主题的分区,并向每个分区发送一条记录。 但正如您所理解的,消息作为一个带有配置参数linger.ms的批处理,它可能会影响小批处理的性能,因为每个批处理都会转到特定的分区,所以Apache Kafka Introductor在出现null键的情况下会提供新的粘性分区

    ApacheKafka在ApacheKafka 2.4中引入了粘性分区器(KIP-480),以防下面提到的默认分区器中的键为null

    粘性分区策略

    sticky partitioner解决了将没有密钥的记录分散成更小的批的问题,方法是选择一个分区来发送所有没有密钥的记录。一旦该分区的批被填充或以其他方式完成,sticky partitioner会随机选择并“粘贴”这样,在一段较长的时间内,记录在所有分区之间的分布基本上是均匀的,同时还可以获得更大批量的额外好处

  • 如果您传递一个非空键,但未定义自定义分区器,则将使用DefaultPartitioner来标识要发布消息的分区。 DefaultPartitioner使用Mu