我有一个kafka主题,有10个分区。我计划在不同的服务器上部署两个应用程序。一个应用程序将从分区0到4读取数据。而另一个将从分区5到9读取。
部署1
@KafkaListener(topicPartitions =
{ @TopicPartition(topic = "testpartition", partitions = { "0", "1","2", "3","4" })
})
public void receive(ConsumerRecord record) {
System.out.println(String.format("Listener 1 -Topic - %s, Partition - %d, Value: %s", kafkaTopic, record.partition(), record.value()));
}
部署2
@KafkaListener(topicPartitions =
{ @TopicPartition(topic = "testpartition", partitions = { "5", "6","7", "8","9" })
})
public void receive(ConsumerRecord record) {
System.out.println(String.format("Listener 2 -Topic - %s, Partition - %d, Value: %s", kafkaTopic, record.partition(), record.value()));
}
因此,当应用程序分别部署在不同的服务器上时,我们将拥有两个消费者组。
因为每个应用程序从不同的分区进行消费这会导致kafka主题上不必要的消息复制吗?
是否所有消息都被复制两次?此外,如果是这种情况,那么会有消息重复吗?这是在分布式环境中部署消费者应用程序的正确方法吗?还是有更好的方法?
由于您是手动分配分区,因此不会有重复,每个实例只会从其分配的分区接收记录。
当你说&;replicated&;;这取决于创建主题时的复制因素。副本用于确保在不同的代理实例上有多个副本,以便处理服务器故障。复制和复制不一样。
但是,即使以这种方式复制记录,每个记录也只有一个逻辑实例。
在某些(罕见的)故障场景中可能会得到重复的记录,除非您启用了一次语义。
另一种部署方式是使用Kafka Group Management,让Kafka使用默认算法或使用自定义的ConsumerPartitionAssignor
来跨实例分发分区。