卡夫卡如何平行消费一个话题

时间:2014-09-01 09:06:05

标签: apache-kafka

我读过kafka文件,还不知道如何消费一个主题并行?

假设: 我有一个主题,如“发生了什么事”(不要拆分这个主题),我有很多客户想要使用它。 那么我应该怎么做,以便多个客户可以并行使用它?我应该使用分区和客户组吗?

我对此有一个想法,但我不确定是否正确。

针对同一主题创建多个分区,并为一个客户创建一个分区,因此一个生产者必须为这些分区生成相同的内容,并且不同客户组中的每个客户都是正确的吗?

4 个答案:

答案 0 :(得分:8)

使用分区是能够并行化主题消费的方式。假设您有10个分区用于您的主题,那么您可以在同一个使用者组中拥有10个消费者,每个消费者组分别读取一个分区。如果您的消费者少于分区,那么他们将分别负责多个分区。如果您拥有的消费者多于分区,那么消费者将无法获得分配给他们的任何分区,除了可以替换另一位已经死亡的消费者之外无所事事。

答案 1 :(得分:8)

Kafka中的每个主题都可以组织成许多分区。分区允许并行消耗,从而提高吞吐量。

生产者使用Kafka生产者客户端库将消息发布到主题,该库使用分区程序在可用分区之间平衡消息。生产者连接到的代理负责使用zookeeper中的分区所有者信息将消息发送到作为该分区的领导者的代理。消费者使用Kafka的高级消费者库(处理经纪人领导者变更,管理zookeeper中的偏移信息并隐含地计算分区所有者信息等)来使用来自流中分区的消息;根据消费者选择创建消息流的方式,每个流可以映射到几个分区。

例如,如果一个主题有10个分区,并且3个消费者实例(C1,C2,C3按此顺序启动)都属于同一个消费者组,我们可以使用不同的消费模型,允许读取并行度,如下所示< / p>

每个消费者使用一个流。在此模型中,当C1启动时,主题的所有10个分区都映射到同一个流,并且C1开始从该流中消耗。当C2启动时,Kafka重新平衡两个流之间的分区。因此,每个流将分配到5个分区(取决于重新平衡算法,它可能也是4对6)并且每个消费者从其流消耗。类似地,当C3启动时,分区再次在3个流之间重新平衡。请注意,在此模型中,当从分配给多个分区的流中进行消费时,消息的顺序将在分区之间混乱。 每个消费者使用多个流(比如C1使用3,C2使用3,C3使用4)。在此模型中,当C1启动时,所有10个分区都分配给3个流,C1可以使用多个线程同时从3个流中消耗。当C2启动时,分区在6个流之间重新平衡,类似地,当C3启动时,分区在10个流之间重新平衡。每个消费者可以同时从多个流中消费。请注意,此处的流和分区数相等。如果流的数量超过分区,则某些流将不会获得任何消息,因为它们不会被分配任何分区。

答案 2 :(得分:0)

@Lundahl 做了所有的教学,我会给你一个实用的样本。

  1. 创建一个具有某种意义的主题,例如news_events 使用您的消费者需要的并行性(分区),您可以使用处理一条消息的时间、您将拥有的消息数量以及您希望处理所有消息的时间来计算它。
  2. 让我们为那个话题创建消费者,你不想看新闻和你的兄弟姐妹,每个人都在你的时间,然后每个人都需要一个消费者组ID,这样kafka就会知道线程a,b ,c 代表一个消费者组,d,e,c 代表第二个消费者组,每个消费者组都会收到相同的消息,按时处理,不会相互影响。
  3. 消息会出现在一个或其他分区,永远不会出现在两个分区,默认情况下 Kafka 会循环选择分区,请记住,所有消费者组都可以连接并从所有相同分区读取数据

我建议您使用 rapids-kafka-client,这是一个为您执行并行处理的库,选择与您拥有的分区数量相等的线程数,选择一个消费者组,然后看看奇迹的发生。< /p>

public static void main(String[] args){
  ConsumerConfig.<String, String>builder()
      .prop(KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName())
      .prop(VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName())
      .prop(GROUP_ID_CONFIG, "news-app")
      .topics("news_events")
      .consumers(7)
      .callback((ctx, record) -> {
        System.out.printf("status=consumed, value=%s%n", record.value());
      })
      .build()
      .consume()
      .waitFor();
}

您可以阅读更多关于消费者组、主题和分区的信息here

答案 3 :(得分:0)

我假设您想要的是客户之间以发布/订阅方式并行消费。

除此之外,您还可以在单​​个客户中进行并行消费,以扩展消费者应用程序。

客户之间平行消费

如果您所说的“客户”是指对独立使用主题消息感兴趣的不同组织,那么您只需要消费者群体

这是一个简单的发布/订阅模式,其中每个客户运行自己的应用程序并阅读所有主题的消息,而不会干扰其他人。 每个客户应用程序都可以被视为一个消费者组,由一个或多个 Kafka 消费者(无论是在单个节点上运行还是分布在集群中)组成,所有这些消费者都共享消费者组的标识符。< /p>

无论分区如何,您都可以实现此目标。如果主题已分区,您无需担心将相同的消息写入所有分区。请记住,在 Kafka 消息 持久 中,Kafka 消费者读取的消息不会被删除,并且可以被来自不同消费者组的其他 Kafka 消费者读取(直到它过期)。此外,分区并不是这样工作的,它们有助于扩展数据存储(在某一点上,所有主题的数据不会只适合一个节点)和扩展消费者应用程序,如下所示。

单个客户并行消费

您可以进一步并行化,或者更好地说,扩展消费者组内的消息消费,实际上是 Kafka 消费者。

想象一下topic很大,生产者写入率很高,消费者组只有一个消费者:这个可怜的消费者可能很难跟上消息到达率,特别是如果消息处理也很耗时。 这就是您需要分区和您的消费者组中更多消费者的情况,以便 Kafka 将分区分配给消费者,以在他们之间分配读取负载。

分区分配的工作原理已经在此处的其他答案中进行了解释,但基本上是针对给定的消费者群体:

  • 每个主题的分区专门分配给一个消费者,
  • 消费者可能会被分配更多的分区
  • 如果消费者不仅仅是主题的分区,他们中的一些人将保持空闲状态,因为他们不会被分配任何分区来消费。

请记住,Kafka中的消息排序仅在分区级别得到保证,因此如果您有很多分区和排序问题,则需要根据您的要求选择正确的消息键对数据进行分区。 例如,如果您希望按设备对消息进行排序,则 device_id 将是您的密钥,以确保将同一设备的消息写入同一分区。