Kafka使用者 - 消费者进程和线程与主题分区的关系是什么

时间:2015-09-09 04:04:21

标签: java multithreading distributed-computing apache-kafka kafka-consumer-api

我最近一直在与卡夫卡合作,对消费者群体下的消费者有点困惑。混淆的中心是将消费者实现为流程还是线程。对于这个问题,假设我正在使用高级消费者。

让我们考虑一下我尝试过的场景。在我的主题中有2个分区(为简单起见,我们假设复制因子只有1)。我使用组ConsumerConnector创建了一个消费者(consumer1)进程group1,然后创建了一个大小为2的主题计数映射,然后生成了2个消费者线程consumer1_thread1和{{1}在那个过程中。看起来consumer1_thread2正在消耗分区consumer1_thread10正在消耗分区consumer1_thread2。这种行为总是确定的吗?以下是代码段。类1是我的消费者线程类。

TestConsumer

现在,让我们考虑另一个场景(我还没有尝试过但很好奇),我开始了2个消费者流程 ... Map<String, Integer> topicCountMap = new HashMap<String, Integer>(); topicCountMap.put(topic, new Integer(2)); Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumer.createMessageStreams(topicCountMap); List<KafkaStream<byte[], byte[]>> streams = consumerMap.get(topic); executor = Executors.newFixedThreadPool(2); int threadNumber = 0; for (final KafkaStream stream : streams) { executor.submit(new TestConsumer(stream, threadNumber)); threadNumber++; } ... consumer1都有相同的群组{{ 1}}并且每个都是单线程进程。现在我的问题是:

  1. 在这种情况下,两个独立的消费者流程(在同一群体下)如何与分区相关?它与上述单进程多线程场景有何不同?

  2. 通常,消费者线程或流程如何映射/与主题中的分区相关?

  3. Kafka文档确实说消费者群体下的每个消费者都会消耗一个分区。但是,这是指消费者线程(如我上面的代码示例)还是独立的消费者流程?

  4. 关于将消费者作为流程与线程实现,我是否有任何微妙的缺点?提前致谢。

2 个答案:

答案 0 :(得分:8)

使用者组可以运行多个使用者实例(具有相同group-id的多个进程)。消耗时,每个分区仅由组中的一个消费者实例消耗

E.g。如果您的主题包含2个分区,并且您启动了具有2个使用者实例的使用者组group-A,那么其中每个实例将使用来自该主题的特定分区的消息。

如果您使用不同的组ID group-A&amp; group-B然后来自该主题的两个分区的消息将被广播到它们中的每一个。因此,在这种情况下,在group-A下运行的消费者实例将包含来自该主题的两个分区的消息,同样适用于group-B

documentation

上详细了解详情

编辑:根据您的评论

  

我想知道在同一个流程下拥有2个消费者线程与2个消费者流程之间的有效区别是什么(两个案例中的组相同) < / p>

整个群集中的消费者group-id是相同/全局的。假设你已经启动了一个有2个线程的进程 - 然后生成另一个进程(可能在不同的机器中),同一个groupId有2个以上的线程,那么kafka将添加这2个新线程来使用来自该主题的消息。因此最终将有4个线程负责从同一主题消费。然后,Kafka将触发重新平衡以将分区重新分配给线程,因此可能会发生对线程T1 of process P1正在使用的特定分区进行分配以供线程T2 of process P2使用。以下几行来自维基页面

  

当使用相同的使用者组名称启动新进程时,Kafka会将该进程的线程添加到可用于使用Topic并触发“重新平衡”的线程集。在此重新平衡期间,Kafka会将可用分区分配给可用线程,可能会将分区移动到另一个进程。如果您混合使用新旧业务逻辑,则某些消息可能会转到旧逻辑。

答案 1 :(得分:0)

感谢@ user2720864的详细回答,但我认为答案中提到的重新分配案例@ user2720864不正确=>一个分区不能由两个使用者使用。

当有更多的使用者(与分区相比)时,每个分区将仅分配给一个使用者,而剩余使用者将保持懒惰,直到某些工作的使用者死亡或从中移出为止。小组。

基于Kafka Consumers document:

  

在Kafka中实现消耗的方式是通过在消费者实例上对日志中的分区进行划分,以使每个实例都是分区中“公平份额”的专有消费者时间。 Kafka协议动态处理了维护组成员身份的过程。如果新实例加入该组,它们将接管该组其他成员的某些分区;如果实例死亡,其分区将分配给其余实例。

还有“ {x3}}(位于“消费者组和主题订阅”部分):

  

这是通过平衡使用者组中所有成员之间的分区来实现的,从而将每个分区分配给该组中的只一个使用者。