卡夫卡:生产者交易后进行轮询并没有得到产生的消息

时间:2018-11-08 23:09:11

标签: transactions apache-kafka kafka-consumer-api kafka-producer-api

我在Kafka有一个使用消费转换技术的应用程序,该应用程序具有一次精确的语义。 (交易的)产生阶段会产生关于同一主题的新消息,然后再使用该消息(transactionally = read_committed)。只有一个线程在执行此操作,并且可以确保在生产者的事务提交之后进行消费者轮询。现在,每轮消耗转换生产只有一个民意测验。

测试用例

在运行测试用例时,有时可能会有其他生产者发送的消息(明确地)在我的生产者的事务提交之前发送。然后我会遇到以下情况:

尽管最后一轮的交易已成功提交,但我的单个民意调查语句仅返回此外来消息,而不返回我刚刚产生的消息。

问题

  1. 我缺少什么东西了吗? 下一轮的消费者看不到一轮?
  2. 在一次轮询返回0条记录之前,我是否必须发出多次轮询?这告诉我该分区中服务器上的所有消息 被阅读?
  3. Kafka可能不保证当前已读取分区上的所有消息吗?也许没有像“我现在已经读完此分区”之类的东西了?

配置

  • 交易消费者

    最终地图消费者配置=新的LinkedHashMap <>();   ConsumerConfig.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,SERVER);   ConsumerConfig.put(ConsumerConfig.CLIENT_ID_CONFIG,ID);   ConsumerConfig.put(ConsumerConfig.GROUP_ID_CONFIG,GROUP_ID);   ConsumerConfig.put(ConsumerConfig.ISOLATION_LEVEL_CONFIG,“ read_committed”);   ConsumerConfig.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,“最新”);   ConsumerConfig.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,“ false”);   ConsumerConfig.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG,“ 100”);   ConsumerConfig.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());   ConsumerConfig.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());

  • 交易产生者

    最终地图producerConfig =新的LinkedHashMap <>();   producerConfig.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,SERVER);   producerConfig.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG,ID);   producerConfig.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());   producerConfig.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());

  • 我的轮询超时为2秒

  • 我的理解是,交易生产者自动成为幂等,acks = all
  • 我的测试用例只有一个代理和一个复制。但是我当然打算在生产中使用更多
  • 我使用Kafka 2.0
  • 我的主题只有一个分区
  • 我的线程有自己的使用者组,并分配给了该单个分区

1 个答案:

答案 0 :(得分:0)

为了理解轮询的工作原理,我们传递给poll()的参数是一个超时间隔,它控制如果使用者缓冲区中没有可用数据,poll()将阻塞多长时间。如果将其设置为0,则poll()将立即返回;否则,返回false。否则,它将等待指定的毫秒数以使数据从代理到达。因此,如果将轮询配置为0毫秒,并且数据缓冲区中没有数据,则不会接收任何数据。

您可能无法接收到最近产生的数据,这取决于您对生产者的配置。除非产生的消息没有其副本且基于acks参数,否则该消息将可供使用者使用。

例如:如果您将副本设置为3且acks = all,除非所有复制者都确认领导者他们已经收到了该消息,否则将不会使此消息可供消费者使用。

这个问题,您怎么知道您是否已读取整个分区,如果您的民意测验不再提供任何记录(假设其余所有工作正常),则表明您已使用了该主题的所有消息