重复生产到 Apache Kafka,不同的偏移量? (恰好一次语义)

Repeatedly produced to Apache Kafka, different offsets? (Exactly once semantics)

在尝试实现 exactly-once 语义时,我在 the official Kafka documentation 中发现了这一点:

Exactly-once delivery requires co-operation with the destination storage system but Kafka provides the offset which makes implementing this straight-forward.

这是否意味着我可以使用(topic, partiton, offset)元组作为唯一主标识符来实现去重? 一个示例实现是使用 RDBMS 和此元组作为大型处理事务中插入操作的主键,如果由于已经存在的主键而无法再插入,事务将失败。

我认为这个问题等同于:

  1. 生产者在检测到可能的失败后重试发送消息时是否对消息使用相同的偏移量,或者每次重试尝试都有自己的偏移量?

如果重试时重用offset,显然消费者会看到多条offset相同的消息。 其他问题,可能有某种相关性:

  1. 单个或多个生产者生产同一个主题,一个消费者看到的偏移量序列中是否可以有"gaps"?

另一种可能性是确定偏移量,例如仅由或最近消息到达执行该工作的领导者(暗示 - 如果不听生产者建议的偏移量 - 可能没有 gaps/offset 跳转,但重复消息也有不同的偏移量,我必须在应用程序级别的应用程序消息中使用我自己的唯一标识符)。

回答我自己的问题:

偏移量仅由服务器生成(更准确地说:由相应分区的领导者生成),而不是由生产客户端生成。然后在 the produce response 中将其发送回生产者。所以:

  1. Does a producer use the same offset for a message when retrying to send it after detecting a possible failure or does every retry attempt get its own offset?

No.(请参阅下面的更新!)生产者不确定偏移量,并且两个 identical/duplicate 应用程序消息可以具有不同的偏移量。因此,偏移量不能用于标识消息以用于生产者重复数据删除目的,并且必须在应用程序消息中定义自定义 UID。 (Source)

  1. With single or multiple producers producing to the same topic, can there be "gaps" in the offset number sequence seen by one consumer?

由于每个分区只有一个领导者维护当前偏移量,并且(使用默认配置)这个领导者只在发生故障时转移到活动的同步副本,我假设在为分区选择新的领导者时总是正确传达最新使用的偏移量,因此最初不应该有任何偏移量间隙或跳跃。但是,由于日志压缩功能,在某些情况下(假设启用了日志压缩),在压缩开始后再次使用分区的已提交消息时,偏移流中确实存在间隙。(Source)

更新(Kafka >= 0.11.0)

从 Kafka 版本 0.11.0 开始,生产者现在会在请求中额外发送一个序列号,然后领导者会使用该序列号根据此编号和生产者 ID 对请求进行重复数据删除。因此,对于 0.11.0,生产者端实现 exactly once 语义的前提条件由 Kafka 本身给出,并且无需在应用程序消息中发送另一个唯一 ID 或序列号。 因此,问题 1 的答案现在也可以是是的,不知何故。 但是,请注意,exactly once 语义仍然只有在消费者永不失败的情况下才有可能。一旦消费者失败,仍然需要注意消费者端的重复消息处理。