卡夫卡一次生产者消费

时间:2020-10-10 11:14:29

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

我正在使用Kafka作为消息代理,为一个简单的数据管道实现完全一次语义。我可以通过设置集合const postsCount = await Post.find(query).countDocuments(); const allPosts = await Post.find(query) .populate('likes') .skip(startIndex) .limit(noOfRecordsPerPage) .sort({ createdAt: 'desc' }); 来强制Kafka生产者将每个生产记录精确地写入一次。

但是,在消耗方面,我需要保证消费者只读取一次每个记录(我不希望将消耗的记录存储到外部系统或刚刚处理的另一个Kafka主题中)。为此,我必须确保处理轮询的记录,并将它们的偏移量以原子方式/事务方式(同时成功/失败)提交给enable.idempotence=true主题。

在这种情况下,我是否需要使用Kafka事务API在消费者轮询循环中创建事务生产者,在事务内部执行以下操作:(1)处理消耗的记录,(2)提交其偏移量,然后完成交易。在这种情况下,正常的commitSync / commitAsync是否可以提供服务?

2 个答案:

答案 0 :(得分:1)

“在消费方面,我需要保证消费者准确地读取每个记录一次”

Gopinath的答案很好地说明了如何在KafkaProducer和KafkaConsumer之间实现一次精确匹配。这些配置(连同KafkaProducer中Transaction API的应用程序)确保了生产者发送的所有数据将只存储在Kafka中一次。但是,它不能保证消费者只读取一次数据。当然,这取决于您的胶印管理。

无论如何,我了解您的问题,您想知道使用者本身是如何一次处理消耗的消息。

为此,您需要以原子方式自行管理偏移。这意味着您需要围绕自己构建“交易”

  • 从Kafka获取数据,
  • 处理数据,并且
  • 将处理过的偏移量存储在外部。

commitSync和commitAsync方法将使您无所适从,因为它们只能确保在Consumer中最多处理一次或最少处理一次。另外,您的处理是幂等的

有一个不错的blog,它解释了一种利用ConsumerRebalanceListener并将其偏移量存储在本地文件系统中的实现。还提供了完整的代码示例。

“我是否需要借助Kafka交易API在消费者轮询循环中创建交易生产者”

Transaction API仅适用于KafkaProducers,据我所知不能用于您的胶印管理。

答案 1 :(得分:0)

卡夫卡中的

'一次'功能可以通过以下三种设置的组合来实现:

  1. isolation.level = read_committed
  2. transactional.id = <unique_id>
  3. processing.guarantee = exactly_once

有关启用一次功能的更多信息:

https://www.confluent.io/blog/simplified-robust-exactly-one-semantics-in-kafka-2-5/

https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/