我正在学习Kafka Stream并使用Processor API来实现我的用例。下面的代码显示了Process方法,该方法将消息转发到下游并在调用std::isdigit
之前中止。这会导致流被重新处理并复制接收器上的消息。
commit
processing.guarantee参数:
public void process(String key, String value) {
context.forward(key, value);
..
..
//killed
context.commit();
}
是否有办法仅在调用streamsConfiguration.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG, StreamsConfig.EXACTLY_ONCE);
语句时应用转发。如果没有,那么实现Exactly-once模式的正确方法是什么。
谢谢
答案 0 :(得分:2)
确保您的接收器处于read_committed
消费者模式,因此它只会看到已提交的消息。如果在事务中止之前将消息写入输出主题,则在中止时,消息仍然存在,只是没有标记为已提交。第二次完成事务,因此将消息和提交标记添加到输出主题。如果您在没有处于read_committed
模式的情况下阅读,那么您将看到所有消息(包括未提交的消息),并且它可能显示为重复消息,因为您会看到已中止的结果和已提交的结果。
来自0.11 javadoc https://kafka.apache.org/0110/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html
在Kafka 0.11.0中引入了交易,其中应用程序可以 以原子方式写入多个主题和分区。为了这个 为了工作,应该配置从这些分区读取的消费者 只读取已提交的数据。这可以通过设置来实现 在消费者的配置中,isolation.level = read_committed。
在read_committed模式下,消费者将只读取那些 已成功提交的事务性消息。它会 像以前一样继续读取非事务性消息。没有 read_committed模式下的客户端缓冲。相反,结束偏移 read_committed使用者的分区的偏移量是 属于开放事务的分区中的第一条消息。 此偏移称为“最后稳定偏移”(LSO)。
read_committed消费者只会读到LSO并过滤掉 任何已中止的交易消息。 LSO也 影响seekToEnd(Collection)和的行为 read_committed消费者的endOffsets(Collection),详细信息 在每种方法的文档中。最后,获取延迟指标是 也调整为相对于read_committed消费者的LSO。 具有事务性消息的分区将包括提交或中止 指示交易结果的标记。有标记 没有返回到应用程序,但在日志中有一个偏移量。作为一个 结果,应用程序从具有事务性消息的主题中读取 将看到消耗的补偿中的差距。这些丢失的消息将是 交易标记,它们被过滤掉给消费者 两种隔离级别。此外,使用read_committed的应用程序 消费者也可能因为交易中止而出现差距 消费者不会返回消息,但会有消息 有效抵消。
答案 1 :(得分:-1)
您可能希望在finally块下包装context.commit()以确保它被调用。但是,您还需要确保在成功处理后确实调用它。