我最近一直在与卡夫卡合作,对消费者群体下的消费者有点困惑。混淆的中心是将消费者实现为流程还是线程。对于这个问题,假设我正在使用高级消费者。
让我们考虑一下我尝试过的场景。在我的主题中有2个分区(为简单起见,我们假设复制因子只有1)。我使用组ConsumerConnector
创建了一个消费者(consumer1
)进程group1
,然后创建了一个大小为2的主题计数映射,然后生成了2个消费者线程consumer1_thread1
和{{1}在那个过程中。看起来consumer1_thread2
正在消耗分区consumer1_thread1
而0
正在消耗分区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}}并且每个都是单线程进程。现在我的问题是:
在这种情况下,两个独立的消费者流程(在同一群体下)如何与分区相关?它与上述单进程多线程场景有何不同?
通常,消费者线程或流程如何映射/与主题中的分区相关?
Kafka文档确实说消费者群体下的每个消费者都会消耗一个分区。但是,这是指消费者线程(如我上面的代码示例)还是独立的消费者流程?
关于将消费者作为流程与线程实现,我是否有任何微妙的缺点?提前致谢。
答案 0 :(得分:8)
使用者组可以运行多个使用者实例(具有相同group-id
的多个进程)。消耗时,每个分区仅由组中的一个消费者实例消耗。
E.g。如果您的主题包含2个分区,并且您启动了具有2个使用者实例的使用者组group-A
,那么其中每个实例将使用来自该主题的特定分区的消息。
如果您使用不同的组ID group-A
&amp; group-B
然后来自该主题的两个分区的消息将被广播到它们中的每一个。因此,在这种情况下,在group-A
下运行的消费者实例将包含来自该主题的两个分区的消息,同样适用于group-B
。
编辑:根据您的评论
我想知道在同一个流程下拥有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中实现消耗的方式是通过在消费者实例上对日志中的分区进行划分,以使每个实例都是分区中“公平份额”的专有消费者时间。 Kafka协议动态处理了维护组成员身份的过程。如果新实例加入该组,它们将接管该组其他成员的某些分区;如果实例死亡,其分区将分配给其余实例。
还有“ {x3}}(位于“消费者组和主题订阅”部分):
这是通过平衡使用者组中所有成员之间的分区来实现的,从而将每个分区分配给该组中的只一个使用者。