Apache kafka kafka如何使用topic/partition/offset实现一次消息传递逻辑

Apache kafka kafka如何使用topic/partition/offset实现一次消息传递逻辑,apache-kafka,spring-kafka,Apache Kafka,Spring Kafka,我设法在用@KafkaListener注释的方法中获得topic/partition/offset,但是如何使用这些数据来实现一个只需一次的使用者逻辑呢 我正在使用ConcurrentKafkListenerContainerFactory,将Concurrent设置为4,并将AckMode设置为手动。 我目前的做法是使用redis进行重复数据消除: 我使用topic:partition作为redis键,offset作为它的值,然后将即将到来的offset与redis中的值进行比较,如果offs

我设法在用@KafkaListener注释的方法中获得topic/partition/offset,但是如何使用这些数据来实现一个只需一次的使用者逻辑呢

我正在使用ConcurrentKafkListenerContainerFactory,将Concurrent设置为4,并将AckMode设置为手动。 我目前的做法是使用redis进行重复数据消除: 我使用topic:partition作为redis键,offset作为它的值,然后将即将到来的offset与redis中的值进行比较,如果offset比redis中的值新(大),那么继续执行业务逻辑,否则我忽略消息。最后提交偏移量(ack.acknowledge())

但这种方法不起作用,例如,如果在ack.acknowledge()完成之前发生了重新平衡,则会出现以下错误:org.apache.kafka.clients.consumer.CommitFailedException

在重新平衡之后,原始分区被分配给另一个线程,这导致相同的消息将被消耗两次


因此,一句话,如何设计一种逻辑,使每个卡夫卡消息只传递一次?

卡夫卡还不支持只传递一次。它将在0.11.0.0版本中提供:
此版本计划于2017年6月14日发布,因此您可以等待或自行构建此复杂逻辑;-)

您必须在卡夫卡之外写出最后一个原子处理的偏移量,以及处理结果。这可以是对数据库或文件的写入,只是不要进行两次写入,而是对数据和偏移量进行一次原子写入。如果您的使用者崩溃,它或另一个实例重新启动或接管,您需要确保它首先读取与上次处理结果一起存储的最后一个偏移量,并在轮询()以获取更多消息之前将()搜索到该位置。这就是目前Kafka接收器连接器可以实现EOS消耗的数量。

我知道Kafka目前不支持它,我只是想知道是否有一种方法我们可以自己实现它……这可能是一个有趣的阅读/起点:Kafka v0.11中的确切语义是:1。从生产者的角度来看,以及2。从卡夫卡流应用的角度来看。然而,从卡夫卡->卡夫卡消费者的角度来看,这并不完全是一次。如果偏移量和应用程序状态存储在外部存储器中,则通用使用者的用户仍然必须实现偏移量和应用程序状态的原子持久性。好主意!因此,为了实现这一点,我需要放弃spring kafka,转而使用kafka官方的低级API。我对spring kafka API不太了解,无法发表评论,但您可以使用kafka Consumer API或kafka Connect API只做一次。在不久的将来,您将能够使用Kafka Streams API,而不必存储Kafka之外的任何内容,因为Kafka本身将支持事务性写入。