问题描述
我们希望使用 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","data");
}
我们期望Kafka中应该只存储一条消息,但实际结果是3条消息。
我怎样才能让 excatly-once 语义与 Kafka 一起工作?
我的配置中缺少什么?
解决方法
Exactly Once 语义不能那样工作,
幂等生产者的配置是为了避免生产者在过程中失败时出现重复或乱序的行,
考虑以下场景: 您向主题发送消息, 您的生产者客户端正在等待经纪人的确认, 该消息已写入 kafka, 但是现在出现网络错误并且从未收到生产者客户端的确认, 您的生产者将进行内部重试以产生消息, 消息将再次发送给代理,
如果您没有启用 idemptance,那么您的经纪人将再次写入消息并向您发送确认, 你会在主题内收到重复的消息,
如果您启用了 idemptance,broker 会理解这是生产者的重试,并且消息已经写入主题,他只会向您发送确认,主题中没有重复。
在您的测试中,您只生成 3 条具有相同值的消息,它们是不同的“线程”...因此您最终将在主题中拥有 3 条消息
为了您的信息,apache kafka 项目非常密集地检查他们添加的所有内容以避免任何破坏性更改,它非常稳定,您可以通过此链接查看他们如何测试 idemptance producer 功能