1. Introduction

  • 从分区读取的消费者可选择何时提交偏移,若在消费者重新启动时
    跳过或读取两次消息,则该策略会影响行为;

2. At Most Once

AtMostOnce
  • 在调用poll()后,一旦收到msg batch,就会提交偏移量,若后续处理失败,
    则消息将丢失,它将不会被再次读取,因消息偏移量已提交,适于能承受数据丢失的系统;

3. At Least Once

AtLeastOnce
  • 来自源系统的每个事件都将到达其目标,但有时重试会导致重复,偏移是在消息处理后提交,
    若处理出错,将再次读取消息,可能导致重复处理消息,适于无法承受任何数据丢失的消费者;

  • 通常是是首选策略,确保处理是幂等的(idempotent,即再次处理消息不会影响系统);

4. Exactly Once

  • 有些应用不仅需at-least-once语义,即没数据丢失,还需exactly-once语义,
    每条消息只传递一次,某些情况下若Kafka和消费者应用合作cooperate,使语义精确一次;

  • 这只能通过使用事务Api实现主题到主题的工作流topic to topic workflow,
    kafka stream简化api的使用,设置:processing.guarantee=exactly.once

  • 对主题到外部系统的工作流topic to external system workflow,
    要有效地实现精确一次effectively achieve exactly once,
    必须使用幂等消费者must use idempotent consumer;

5. Summary

Entry Memo

At Most Once

一旦收到消息,就提交偏移,若处理出错,消息将丢失,不会再次读取

At Least Once

在处理消息后提交偏移量,若处理出错,将再次读取消息,
可能导致重复处理消息,确保处理幂等,即再次处理消息不影响系统

Exactly Once

可使用高级Stream Api或低级Transactions
Api,实现Kafka ⇒ Kafka workflow,
对Kafka ⇒ Sink workflow,请使用幂等idempotent消费者

  • 对大多应用,应使用"At Least Once"处理,并确保转换/处理
    transformation/processing是幂等idempotent;

6. Automatic Offset

AutomaticCommitting
  • Consumer Java Api会定期自动提交偏移量,以便启用at-least once读取场景;

  • https://www.conduktor.io/kafka/kafka-consumer-groups-and-consumer-offsets

  • 默认:属性enable.auto.commit=true,故偏移量
    以配置auto.commit.interval.ms控制的频率自动提交;

  • 提交偏移量的过程发生在以下情况:

    • call poll();

    • 两次调用poll()之间的时间大于设置auto.commit.interval.ms(默认5s);

  • 即要处于"at-least-once"处理用例(最理想的用例)中,需确保
    在执行另一个poll()调用之前成功处理消费者代码中的所有消息;

  • 若不是此种情况,那偏移量可能会在消息实际处理之前提交,
    从而导致"at-most once"的处理模式,可能导致消息
    跳过skipping,这是不可取的undesirable;

  • 在此罕见(rare)情况下,必须禁用enable.auto.commit,且很可能禁用对单独线程
    的大多数处理,然后不时手动调用具有正确偏移量的commitSync()或commitAsync();