【问题标题】:Kafka Topic design best approachKafka 主题设计最佳方法
【发布时间】:2020-09-28 16:24:33
【问题描述】:

我们正在设计一个使用 apache Kafka 的集成来发送关键业务数据。我们有一个生产者和 5 个消费者,所以我创建了一个包含 5 个分区的主题来为每个消费者分配一个分区,但是我们需要按照生产者发送的相同顺序传递信息,但我们无法实现。我读过我只能按分区实现排序,所以如果我只有一个分区,我应该能够做到,但由于我有 5 个消费者,我需要分区来并行化主题。所以我认为我必须使用主题键,但由于顺序仅由分区保证,我有一些问题: 如果我在 Kafka 生产者中使用密钥,我应该发送指定分区号的有效负载(即在生产者代码中写入消息 5 次,每个分区一个)?或者仅通过向主题发送带有密钥的数据,kafka 复制并写入每个分区中的数据顺序相同? 示例:

for(int i=0;i<=partitionsnumber;i++){ sendtoKafka(i,key,payload); }

在这种情况下,我应该为每个消费者使用一个主题而不是分区吗?

以相同顺序向所有消费者发送数据的最佳策略是什么?

注意:消息中唯一的键是字符串类型。

【问题讨论】:

    标签: apache-kafka


    【解决方案1】:

    评论太长了,无法添加。

    您在评论中提到“我们需要相同数量的消费者应用程序分区”是正确的。但是,它仅适用于所有消费者(在您的情况下为 5 个)属于同一消费者组的情况。

    例如,一个主题 T5 个分区,现在假设我们创建一个消费者 C1 与消费者组 G1强>。消费者c1会从Topic T的所有5个分区中获取消息。然后,我们将消费者c2添加到同一个消费者组G1下。 c1 将消耗 3 个分区,c2 将从剩余 2 个分区消耗(反之亦然)。现在你提到的——“每个消费者应用程序一个分区”是一种理想的场景,在这种情况下,同一消费者组 (G1) 下的 5 个消费者可以从所有 5 个分区并行消费。这个概念称为可扩展性。

    现在,在您的情况下,您需要读取 5 次相同的数据,因为您有 5 个消费者。在这种情况下,您可以编写一个简单的生产者应用程序,将数据发布到具有 1 个分区的主题上,而不是将相同的消息发布到 5 个分区,然后消费来自所有 5 个消费者的相同消息。然后,您的 5 个消费者应用程序可以独立使用相同的数据,即我告诉您为所有消费者应用程序分配随机的消费者组名称,以便它独立地使用消息(以及提交偏移量)。

    在代码sn-p下面。两个消费者并行消费来自同一个 Topic(1 个分区)的消息:

    消费者1:

     Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString()); // randomise consumer group for consumer 1. 
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArrayDeserializer");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
    
                KafkaConsumer consumerLiveVideo = new KafkaConsumer(props);
                consumerLiveVideo.subscribe(Collections.singletonList(topicName[0])); // topic with 1 partition
    

    消费者2:

    Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString()); // randomise consumer group for consumer 2 . 
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArrayDeserializer");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
    
                KafkaConsumer consumerLiveVideo = new KafkaConsumer(props);
                consumerLiveVideo.subscribe(Collections.singletonList(topicName[0])); // topic with 1 partition
    

    您还询问了正确的方法,据我说,您只需要一个消费者应用程序。另外,不要在 Kafka 中混用复制和可扩展性的概念,因为这两者都非常重要。

    另外,关于关键数据,你已经说过了,你可以阅读 Producer 配置参数 acks(根据你的场景使用参数 acks =1 或 acks=all)。

    有关可扩展性、复制、消费者组、消费者/生产者/经纪人/主题的更多详细信息,请阅读 Kafka The Definitive Guide 的第 1-5 章。

    【讨论】:

    • 您好 Simran,感谢您再次回答,您的回答很棒而且非常明确。只有一个问题:我如何决定是否应该使用一个或多个消费者组?我能理解的取决于我需要传递数据的方式。
    • 嗨@avgosim,简单的答案是当您想从由多个分区组成的主题中并行消费消息时,请使用消费者组。例如,2 个消费者应用程序想要消费来自 2 个分区的主题的消息。两个消费者应用程序必须有一个消费者组,以确保它们并行消费消息。有关更多详细信息,请阅读 Kafka The Definitive Guide 一书的第 4 章 - “Kafka 消费者:从 Kafka 读取数据”。如果您对我的回答感到满意,请接受它们或放弃投票。谢谢
    【解决方案2】:

    您需要所有消费者阅读生产者发布的相同消息,对吗?

    如果是这样,您不必向主题的所有 5 个分区发布/生成相同的消息

    更简单的方法是创建一个具有 1 个分区的主题,然后您的生产者应用会将所有消息发布到该主题/分区。

    现在,您可以轻松地创建具有不同消费者群体的消费者应用程序 使用来自同一主题的数据。 为您的消费者分配一些随机 ID,这样您就可以从一个主题/分区与所有 5 个消费者一起消费,并能够提交偏移量。

    只需将以下代码 sn-p 添加到所有 5 个消费者应用程序属性即可。

    props.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString()); // randomise consumer group.
    

    如果您有任何问题,请告诉我。

    【讨论】:

    • 您好 Simran,感谢您的回答。是的,我需要所有消费者都可以按照我生产它们的顺序从该主题获取消息,但是我的理解是,如果分区数小于消费者数,它可能会产生性能问题,这是不好的做法。我不知道每个消费者都需要一个分区,这种方法有问题吗?另一方面,消费者群体如何在这里提供帮助?请您解释一下。
    • 如果您不希望每个消费者处理相同的消息,则每个消费者需要 1 个分区。 IE ....您每秒向主题发布 100 条消息,而您的消费者每秒只能处理 10 条消息。所以你需要 10 个消费者来跟上。然后你会想要 10 个分区,但每个消费者每 100 条消息只能处理 10 条消息。
    • 如果您希望多个消费者根据相同的消息执行不同的工作。然后你可以有 1 个分区,但有多个消费者使用不同的消费者组 ID。您可以通过将多个分区与消费者组混合在一起,每个组使用不同的组 ID。
    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 2017-04-03
    相关资源
    最近更新 更多