Apache Kafka:查找和分配。从头开始可靠阅读

时间:2018-10-31 17:27:11

标签: java apache-kafka kafka-consumer-api

我正在尝试实现基本方案,从头开始阅读主题(至少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个。看来终于奏效了。

所以问题是:

  1. seekToBeginning之后subscribe没用吗?应该记录下来吗?
  2. ConsumerRebalanceListener解决方案是否可靠?是否可以确保在应用搜索之前不会轮询来自中间(承诺偏移量)的消息?

1 个答案:

答案 0 :(得分:2)

第一个

您在问题中正确提到了这一点,即seek()seekToXXXX()操作的先决条件是需要分配分区。只有加入消费者小组,这种情况才会发生,并且只有在我们致电poll()时才会发生。因此,seek()操作不会在subscribe()之后立即起作用。

这实际上记录在《卡夫卡权威指南》第4章“卡夫卡消费者”中的“使用特定偏移量消费记录”中。

第二个问题

是的,根据Kafka的权威指南,使用ConsumerRebalanceListener是可靠的并且是推荐的方法。

以下是同一章的声明,该声明确认了相同的内容:

  

有很多不同的方法来实现一次语义   ...................,但所有人都会   需要使用ConsumerRebalance Listener和seek()来确保   偏移量被及时存储,消费者开始阅读   来自正确位置的邮件。

希望这会有所帮助!