【发布时间】:2019-08-02 00:04:42
【问题描述】:
在 Kafka 文档中,提到消费者不是线程安全的。为了避免这个问题,我读到为每个 Java 进程运行一个消费者是个好主意。如何实现?
消费者的数量没有定义,但可以根据需要改变。
谢谢, 阿莱西奥
【问题讨论】:
标签: java multithreading apache-kafka
在 Kafka 文档中,提到消费者不是线程安全的。为了避免这个问题,我读到为每个 Java 进程运行一个消费者是个好主意。如何实现?
消费者的数量没有定义,但可以根据需要改变。
谢谢, 阿莱西奥
【问题讨论】:
标签: java multithreading apache-kafka
您说得对,文档指定 Kafka 消费者不是线程安全的。但是,它还说您应该在单独的线程上运行消费者, 不是进程。那是完全不同的。有关面向 Java/JVM 的更多细节的答案,请参见此处: https://stackoverflow.com/a/15795159/236528
一般来说,您可以在一个 Kafka 主题上拥有任意数量的消费者。其中一些可能共享一个group id,在这种情况下,该主题的所有分区将分布在任何时间点处于活动状态的所有消费者中。
关于 Kafka 消费者的 Javadoc 有更多详细信息,链接在此答案的底部,但我复制了以下文档建议的两个线程/消费者模型。
1.每个线程一个消费者
一个简单的选择是给每个线程自己的消费者实例。这里 这种方法的优缺点是:
专业版:最容易实现
专业人士:它通常是最快的,因为不需要线程间协调
专业人士:它使得在每个分区的顺序处理非常容易实现(每个线程只是按照接收消息的顺序处理消息)。
CON:更多的消费者意味着更多的 TCP 连接到集群(每个线程一个)。一般来说,Kafka 非常有效地处理连接,因此这通常是一个很小的成本。
缺点:多个消费者意味着更多的请求被发送到服务器,并且数据批处理稍微减少,这可能会导致 I/O 吞吐量有所下降。
CON:所有进程的总线程数将受到分区总数的限制。
2。解耦消费和处理
另一种选择是拥有一个或多个消费者线程 所有数据消耗并将 ConsumerRecords 实例移交给 由处理器线程池消耗的阻塞队列,实际上 处理记录处理。此选项同样有利有弊:
专业版:此选项允许独立扩展消费者数量 和处理器。这使得有一个单一的消费者成为可能 提供许多处理器线程,避免对分区的任何限制。
CON: 保证处理器间的顺序需要特别小心 因为线程将独立执行较早的数据块 实际上只是由于运气而在稍后的数据块之后处理 线程执行时间。对于没有排序的处理 要求这不是问题。
CON:手动提交 位置变得更难,因为它要求所有线程协调 确保该分区的处理完成。有许多 这种方法的可能变化。例如每个处理器 线程可以有自己的队列,消费者线程可以散列到 这些队列使用 TopicPartition 来保证有序消费 并简化提交。
根据我的经验,选项 #1 最适合开始使用,只有在确实需要时才可以升级到选项 #2。选项 #2 是从 kafka 消费者中提取最大性能的唯一方法,但它的实现更复杂。因此,请先尝试选项 #1,看看它是否适合您的特定用例。
完整的 Javadoc 可在此链接中找到: https://kafka.apache.org/23/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html
【讨论】: