【Kafka】Kafka能做到Exactly-once语义吗?

Kafka本身无法提供exactly-once语义,只能保证at least once。但是通过一些手段,可以近似实现exactly-once的语义:

1. 事务性生产者(Transactional Producer)

使用Kafka支持的Transactional Producer可以提供exactly-once的语义。每个事务要么被全部应用,要么全部忽略。

举例

## www.itzhimei.com 代码演示
producer.initTransactions();
producer.beginTransaction();

for (message: messages) 
    producer.send(message);

producer.commitTransaction();
//或 
producer.abortTransaction();

2.幂等消费者(Idempotent Consumer)

保证消费者具有幂等性,即使消息被多次消费也只产生一个效果。这可以近似实现exactly-once。

举例

## www.itzhimei.com 代码演示
public void process(Message msg) {
    // 检查消息是否已经被处理过
    if (isHandled(msg)) 
        return;
    // 幂等处理消息        
    idempotentHandle(msg); 
    // 修改已经处理的状态     
    markHandled(msg);
}

3.端到端事务

使用两个事务,分别记录offset和处理结果。只有两个事务都成功,才算消息被成功处理。

以上方法可以让Kafka近似提供exactly-once语义:

  1. 使用事务性生产者
  2. 消费者具备幂等性
  3. 端到端事务

其中使用事务性生产者和幂等消费者最简单实用。但仍然无法 100%提供exactly-once语义,主要局限在生产者端。

Kafka本身只能保证at least once,但是通过事务性生产者和幂等消费这两种方式,可以近似实现exactly-once语义。