我正在尝试实现基本方案,从头开始阅读主题(至少1条消息),并且遇到意外的行为。
假设有1个分区主题正好保存了100万条消息,有1个使用偏移量的使用者已经在中间某个地方提交了消息,而没有活跃的生产者。
首先我尝试过
consumer.subscribe(Collections.singletonList(topic));
consumer.seekToBeginning(Collections.emptySet());
consumer.poll(Duration.ofMillis(longTimeout)); //no loop to simplify
那是行不通的(没有轮询消息)。我已经读过seekToBeginning
是懒惰的(没关系),但是事实证明,seekToBeginning
完全没有影响,因为它需要已经分配了分区,只有先执行轮询。应该在文档中描述它,还是错过了?
然后我尝试了
consumer.subscribe(Collections.singletonList(topic));
consumer.poll(Duration.ofMillis(assignTimeout));
consumer.seekToBeginning(Collections.emptySet());
consumer.poll(Duration.ofMillis(longTimeout));//no loop to simplify
事实证明,这取决于assignTimeout
。它应该足以完成加入过程。时间可能会有所不同,因此无法依靠它。
然后我为ConsumerRebalanceListener
提供了
@Override
public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
consumer.seekToBeginning(partitions);
}
还有poll
个。看来终于奏效了。
所以问题是:
seekToBeginning
之后subscribe
没用吗?应该记录下来吗?ConsumerRebalanceListener
解决方案是否可靠?是否可以确保在应用搜索之前不会轮询来自中间(承诺偏移量)的消息?答案 0 :(得分:2)
第一个:
您在问题中正确提到了这一点,即seek()
或seekToXXXX()
操作的先决条件是需要分配分区。只有加入消费者小组,这种情况才会发生,并且只有在我们致电poll()
时才会发生。因此,seek()
操作不会在subscribe()
之后立即起作用。
这实际上记录在《卡夫卡权威指南》第4章“卡夫卡消费者”中的“使用特定偏移量消费记录”中。
第二个问题:
是的,根据Kafka的权威指南,使用ConsumerRebalanceListener
是可靠的并且是推荐的方法。
以下是同一章的声明,该声明确认了相同的内容:
有很多不同的方法来实现一次语义 ...................,但所有人都会 需要使用ConsumerRebalance Listener和seek()来确保 偏移量被及时存储,消费者开始阅读 来自正确位置的邮件。
希望这会有所帮助!