如何在 Spring Boot 中设置 Kafka 幂等生产者?

How to setup Kafka Idempotent Producer in Spring Boot?

我们希望使用 exactly-once 语义在 Kafka 中存储数据以避免消息重复。 具有以下属性的生产者:

spring.kafka.producer.properties.acks=all
spring.kafka.producer.properties.enable.idempotence=true

Kafka 主题描述:

Topic: topicName    PartitionCount: 1   ReplicationFactor: 1    
Configs: Topic: topicName   Partition: 0    Leader: 1   Replicas: 1 Isr: 1

集成测试:

  @Test
  void exactlyOnceTest() {
    kafkaTemplate.send("topicName", "key", "data");
    kafkaTemplate.send("topicName", "key", "data");
    kafkaTemplate.send("topicName", "key", "data");
  }

我们的期望是Kafka中应该只存储1条消息,但实际结果是3条消息。

如何使 excatly-once 语义与 Kafka 一起工作?

我的配置中缺少什么?

Exactly Once 语义不能那样工作,

配置幂等生产者是为了避免生产者在此过程中失败时出现重复或乱序的行,

考虑以下场景: 您向主题发送消息, 您的生产者客户正在等待经纪人的确认, 消息被写入卡夫卡, 但是现在出现网络错误并且生产者客户端从未收到确认, 您的制作人将进行内部重试以生成消息, 消息将再次发送给代理,

如果您没有启用 idemptance 那么您的经纪人将再次写消息并向您发送确认, 您会在主题中收到重复的消息,

如果你启用了 idemptance,broker 会理解这是生产者的重试,并且消息已经写入主题,他只会向你发送确认,主题中没有重复。

在您的测试中,您只生成了 3 条具有相同值的消息,它们是不同的“线程”...因此您最终将在主题中包含 3 条消息

供您参考,apache kafka 项目正在非常密集地检查他们添加的所有内容,以避免任何重大更改,它非常稳定,您可以看看他们是如何测试 idemptance producer 功能的 link

https://github.com/apache/kafka/blob/c5ec390fa6fded24dee5d699a0ec87a5345a4e99/clients/src/test/java/org/apache/kafka/clients/producer/KafkaProducerTest.java#L160