Kafka 中实现 Exactly Once Semantics(EOS,精确一次语义),是为了确保:
每条消息被处理一次且仅一次,既不会丢失,也不会重复消费。
这是一种在分布式消息系统中非常难实现的语义。Kafka 从 0.11 版本 开始支持 EOS,到现在已经非常成熟。下面我们详细看看 Kafka 是如何实现它的。
🧠 先理解三种消息语义
消息语义 | 意义 | 是否可能重复 |
---|---|---|
At Most Once | 最多一次(可能丢) | ❌ 不重复,但可能丢 |
At Least Once | 至少一次(可能重复) | ✅ 可能重复 |
Exactly Once | 恰好一次(不丢不重) | ✅ 理想状态 |
✅ Kafka 实现 Exactly Once 依赖两大核心机制:
1. 幂等性生产(Idempotent Producer)
防止同一条消息因重试而被写入多次。
- 开启方式:
enable.idempotence=true
- 作用:
- 保证 单个 producer -> 单个 topic partition 不会因重试导致重复写入。
- 自动开启
acks=all
和retries > 0
。
2. 事务性写入(Kafka Transactions)
保证 多条消息的原子写入,以及消费 offset 与消息写入绑定在一个事务内。
- 开启方式(Java 示例):
props.put("enable.idempotence", "true"); props.put("transactional.id", "my-tx-id"); producer.initTransactions();
- 使用流程:
producer.beginTransaction();// 处理消息 & 发送结果 producer.send(...); producer.send(...);// 将消费 offset 也作为事务提交的一部分 producer.sendOffsetsToTransaction(offsets, consumerGroupId);producer.commitTransaction(); // 或 abortTransaction();
🔁 Kafka Exactly Once 的处理流程图解:
┌────────────┐ ┌──────────────────┐ ┌────────────────────┐
│ Consumer A │ │ Kafka Producer │ │ Kafka Broker │
└────┬───────┘ └────────┬─────────┘ └────────┬───────────┘│ │ ││ poll() 数据 │ ││────────────▶ │ ││ │ send() 数据 ││ ├────────────────────────────▶││ │ sendOffsetsToTransaction() ││ ├────────────────────────────▶││ │ commitTransaction() ││ ├────────────────────────────▶│
🚀 事务提交成功后:
- 所有写入的数据才对消费者可见。
- offset 也一起提交,保证“处理 + offset 提交”是一体的。
✅ Kafka Exactly Once 的关键保障点
机制 | 作用 |
---|---|
幂等性生产者(Idempotence) | 避免 producer 重试时重复发送消息 |
事务性 producer | 保证一批消息要么都写入,要么都不写 |
sendOffsetsToTransaction | 把 offset 也纳入事务中,确保“处理一次” |
read_committed 模式 | 消费者只读取已提交的事务数据 |
🧱 使用 EOS 的完整配置建议
# Producer
enable.idempotence=true
transactional.id=my-unique-id
acks=all
retries=Integer.MAX_VALUE
max.in.flight.requests.per.connection=5 (Kafka 2.4+)# Consumer
isolation.level=read_committed
enable.auto.commit=false
⚠ 注意事项
transactional.id
必须在整个 producer 生命周期中保持唯一。- 事务机制略有性能开销,不适合低延迟、超高吞吐但容忍重复的场景。
- 不能实现跨系统 EOS(比如 Kafka + DB),需要使用二阶段提交或外部协调机制。
✅ 总结一句话
Kafka 的 Exactly Once = 幂等 + 事务 + 消费 offset 一体提交 + 只读已提交数据。
它适用于:
- 金融交易
- 订单系统
- 数据管道(ETL)
- CDC 数据一致性保障