首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Apache中,为什么不能有比分区更多的使用者实例?

在Apache中,为什么不能有比分区更多的使用者实例?
EN

Stack Overflow用户
提问于 2014-09-17 16:48:18
回答 6查看 73K关注 0票数 102

我正在学习卡夫卡,在这里阅读导言一节

https://kafka.apache.org/documentation.html#introduction

特别是关于消费者的那部分。导言的第二至最后一段内容如下:

卡夫卡做得更好。通过在主题中具有并行性--分区--的概念,Kafka能够为用户进程池提供排序保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的,这样每个分区就会被组中的一个消费者使用。通过这样做,我们确保使用者是该分区的唯一读者,并按顺序使用数据。由于有许多分区,这仍然平衡了许多使用者实例的负载。但是,请注意,不能有比分区更多的使用者实例。

我的困惑源于最后一句,因为在作者描述两个消费者组和一个4分区主题的那一段的图像中,消费者实例比分区多!

而且,不能有比分区更多的使用者实例也是没有意义的,因为这样的分区将非常小,而且似乎为每个消费者实例创建新分区的开销会使Kafka陷入困境。我知道分区用于容错和减少任何一台服务器上的负载,但是在分布式系统的上下文中,上面的句子是没有意义的,因为分布式系统应该能够同时处理成千上万的用户。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-09-19 23:33:31

好的,要理解它,我们需要理解几个部分。

  1. 为了提供订购总订单,该消息只能发送给一个消费者。否则,它将效率极低,因为它需要等待所有消费者在发送下一条消息之前收到该消息:

但是,尽管服务器按顺序分发消息,但消息是异步传递给使用者的,因此它们可能会在不同的使用者上出现故障。这实际上意味着在并行消费的存在下,消息的排序会丢失。消息传递系统通常通过一个只允许一个进程从队列中使用的“独占使用者”的概念来解决这个问题,但这当然意味着在处理中没有并行性。 卡夫卡做得更好。通过在主题中具有并行性--分区--的概念,Kafka能够为用户进程池提供排序保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的,这样每个分区就会被组中的一个消费者使用。通过这样做,我们确保使用者是该分区的唯一读者,并按顺序使用数据。由于有许多分区,这仍然平衡了许多使用者实例的负载。但是,请注意,不能有比分区更多的使用者实例。 Kafka只对分区内的消息提供总的顺序,而不是在主题中的不同分区之间提供总顺序。

另外,您认为性能损失(多个分区)实际上是性能提高,因为Kafka可以完全并行地执行不同分区的操作,同时等待其他分区完成。

  1. 图中显示了不同的使用者组,但是每个分区最大一个使用者的限制仅在一个组内。您仍然可以拥有多个消费群体。

在开始时,描述了这两种情况:

如果所有的使用者实例都有相同的使用者组,那么这就像传统的队列平衡负载在使用者身上一样。 如果所有的使用者实例都有不同的使用者组,那么这就像发布-订阅一样,所有的消息都被广播给所有的使用者。

因此,您拥有的订阅组越多,性能就越低,因为kafka需要将消息复制到所有这些组,并保证全部订单。

另一方面,分组越少,分区越多,就越能从消息处理中获得更多好处。

票数 93
EN

Stack Overflow用户

发布于 2016-04-01 20:21:28

重要的是要记住,Kafka为每个消费者群体、主题、分区保留了一个偏移量。这就是原因。

我猜这句话

但是,请注意,不能有比分区更多的使用者实例。

指的是“自动消费者组再平衡”模式,默认的消费者模式是当您只订阅()一定数量的消费者到一个主题列表。

我假设这是因为,至少对于Kafka 0.9.x,没有什么可以阻止有多个使用者实例,来自同一个组的成员从同一个分区读取。

您可以在两个或多个不同的线程中这样做。

代码语言:javascript
复制
Properties props = new Properties();
props.put(ConsumerConfig.GROUP_ID_CONFIG, "MyConsumerGroup");
props.put("enable.auto.commit", "false");
consumer = new KafkaConsumer<>(props);
TopicPartition partition0 = new TopicPartition("mytopic", 0);
consumer.assign(Arrays.asList(partition0));
ConsumerRecords<Integer, String> records = consumer.poll(1000);

并且您将有两个(或更多)消费者从同一个分区读取数据。

现在,“问题”是,两个消费者将共享相同的偏移量,您没有其他选择,因为只有一个组,主题和分区发挥作用。

如果两个使用者同时读取当前偏移量,那么两个使用者都会读取相同的值,并且都会得到相同的消息。

如果您希望每个使用者读取不同的消息,则必须同步它们,以便只有一个用户可以在同一时间获取和提交偏移量。

票数 13
EN

Stack Overflow用户

发布于 2018-11-18 22:15:35

Kafka消费者组模型是一种排队机制的混合体,其中一个消费者实例读取的消息立即从队列中删除,而pub/sub机制则是消息在保留期设置或到期之前才被删除的混合机制,并可供所有消费者实例使用直到过期。因此,如果您有要使用的用例--这是一个pub/sub模型,但希望将它用作排队机制,那么您可以为您的所有消费者实例创建使用者组。给定Kafka在单个使用者组内的使用者实例之间分配分区,保证只处理1条消息一次。如果Kafka允许你在一个单一的消费群体中拥有更多的消费者实例,那么它就超越了拥有消费者群体的目的。

考虑一下这个例子:

REST pub1向topic1发布了4条消息,该topic1有4个分区( part1通过part4 ),因此每个部分都有1条消息。

您有2个微服务、sub1和sub2作为订阅服务器,每个微服务有4个实例正在运行。

现在,如果创建两个消费者组,每个miroservice sub1instance1将有一个映射到part1,sub1instance2将映射到part2等,同样,sub2instance1将映射到part1,sub2instance2将映射到part2等。

只要每个使用者组中的使用者实例少于或等于分区数,微服务的每个实例将只处理一次消息。在本例中,sub1instance1和sub2instance将处理来自part1的msg1。

如果消费者实例多于分区,那么Kafka将不得不为多个使用者实例分配相同的分区,因此每个映射到该分区的使用者实例将多次处理消息。这就是为什么Kafka阻止我们在消费者组中拥有比订阅的主题中的分区数量更多的使用者实例的原因。

希望这是有意义的。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25896109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档