具有相同GroupId的多个Kafka侦听器全部接收消息

时间:2019-06-11 20:38:37

标签: java spring spring-boot apache-kafka spring-kafka

我在Spring Boot应用程序中配置了一个kafka侦听器,如下所示:

@KafkaListener(topicPartitions = @TopicPartition(topic = 'data.all', partitions = { "0", "1", "2" }), groupId = "kms")
public void listen(ObjectNode message) throws JsonProcessingException {
    // Code to convert to json string and write to ElasticSearch
}

此应用程序已部署到3台服务器上并在其中运行,尽管它们的组标识均为kms,但它们都获得了消息的副本,这意味着我在Elastic中获得了3条相同的记录。当我在本地运行实例时,会写入4个副本。

我已经确认生产者通过检查写入前后主题上所有消息的计数来仅向该主题写入1条消息;它只会增加1。如何预防呢?

2 个答案:

答案 0 :(得分:2)

当您手动分配分区时,您负责在实例之间分配分区。

该组将被忽略。

您必须使用组管理并让Kafka为您分配分区,或者为每个实例手动分配分区。

使用topicPartitions代替topics = "data.all"

答案 1 :(得分:0)

不手动分配分区会发生什么情况

生产者方

  • 当生产者发送一条消息时,没有采取任何策略或指定应将哪个分区消息发送至目的地时,kafka会尝试使用循环轮询技术,并将所有消息拆分到所有可用分区中。
    • 2个分区中的消息是唯一的,因为建议最多只有1个使用者来收听主题的特定分区。

消费者方面

  • 例如,一个主题有2个分区
  • 然后,一个消费者(让我们说A)与消费者组(让我们说consumer)加入
  • 每当新的使用者加入并为A分配2个分区时就会发生分区重新分配,因为我们只有一个使用者组consumer
  • 现在,消费者B尝试加入同一消费者组consumer,然后再次发生分区重新分配,并且A和B都将获得分区以收听消息
  • 由于我们只有2个分区,因此即使将更多消费者都添加到同一个消费者组,也将只有2个消费者正在收听发送给该主题的消息,因为一次只有2个消费者可以获得1-1划分。为了保持消费者使用的消息的排他性。

您的情况是,有1个以上的使用者正在收听相同的分区,因此所有正在收听同一使用者组中相同分区的使用者也将从该分区接收消息。因此,由于一个以上的消费者正在监听相同的分区,因此消费者组中消费者之间的互斥性消失了。