一尘不染

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

java

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

让我们考虑一个我尝试过的场景。在我的主题中,有2个分区(为简单起见,我们假设复制因子仅为1)。我创建了一个消费者(ConsumerConnector)过程consumer1与组group1,然后创建尺寸2的主题计数地图,然后产生了2个消费者线程consumer1_thread1consumer1_thread2该过程下。看起来好像consumer1_thread1正在消耗分区,0而且consumer1_thread2正在消耗分区1。这种行为是否总是确定性的?下面是代码片段。类TestConsumer是我的使用者线程类。

    ...
    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++;
    }
    ...

现在,让我们考虑另一个场景(我还没有尝试过,但是很好奇),其中我启动了2个消费者进程,consumer1并且consumer2它们都具有相同的组,group1并且每个进程都是一个单线程进程。现在我的问题是:

  1. 在这种情况下,两个独立的使用者进程(仍然在同一个组中)如何与分区相关?与上述单进程多线程方案有何不同?

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

  3. Kafka文档确实指出,消费者组下的每个消费者都将使用一个分区。但是,这是指使用者线程(例如上面的代码示例)还是独立的使用者进程?

  4. 关于将消费者实现为流程还是线程,我在这里是否缺少任何微妙的东西?提前致谢。


阅读 253

收藏
2020-12-03

共1个答案

一尘不染

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

例如,如果您的主题包含2个分区,并且您group-A使用2个使用方实例启动一个使用方组,则每个使用方实例将使用该主题的特定分区中的消息。

如果您使用不同的组ID
group-A和启动相同的2个使用者,group-B则该主题的两个分区中的消息将广播到其中每个。因此,在这种情况下,在其下运​​行的使用者实例group-A将具有来自该主题的两个分区的消息,这同样适用group-B

在他们的文档中阅读有关此内容的更多信息

编辑 :根据您的评论,

我想知道在相同的流程中拥有2个使用者线程而不是2个使用者进程(两种情况下的组相同)之间的有效区别是什么?

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

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

2020-12-03