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语义:
- 使用事务性生产者
- 消费者具备幂等性
- 端到端事务
其中使用事务性生产者和幂等消费者最简单实用。但仍然无法 100%提供exactly-once语义,主要局限在生产者端。
Kafka本身只能保证at least once,但是通过事务性生产者和幂等消费这两种方式,可以近似实现exactly-once语义。