外观
一句话答案
Kafka 精确一次语义:幂等 Producer(PID+序列号去重)+ 事务性写入(跨 Partition 原子)+ 消费端业务幂等。
核心要点
三种消息语义:
| 语义 | 含义 | 实现难度 |
|---|---|---|
| At Most Once | 消息最多被消费一次(可能丢失) | 最简单 |
| At Least Once | 消息至少被消费一次(可能重复) | 较简单 |
| Exactly Once | 消息恰好被消费一次(不丢不重) | 最复杂 |
Kafka Exactly-Once 的两层实现:
1. 生产者幂等性(Idempotent Producer)
properties
enable.idempotence=true # Kafka 3.0+ 默认开启1
- 每个 Producer 分配唯一的
PID(Producer ID) - 每条消息附带单调递增的
Sequence Number - Broker 根据
<PID, Partition, SeqNum>去重,重复的消息不会被写入 - 范围:仅保证单 Producer、单 Partition、单 Session 的幂等
2. 事务(Transactional Producer + Consumer)
java
// 生产者
producer.initTransactions();
producer.beginTransaction();
try {
producer.send(record1);
producer.send(record2);
producer.sendOffsetsToTransaction(offsets, groupMetadata); // 提交消费位移
producer.commitTransaction();
} catch (Exception e) {
producer.abortTransaction();
}
// 消费者
props.put("isolation.level", "read_committed"); // 只读已提交的消息1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- 引入
Transaction Coordinator和__transaction_state内部 Topic - 将消息写入 + Offset 提交放在同一个事务中
- 消费者设置
isolation.level=read_committed,只读取已提交事务的消息 - 范围:保证跨 Partition、跨 Topic 的原子性
实际应用场景:
- Kafka Streams 内部使用事务实现 Exactly-Once 流处理
- 消费-处理-生产(consume-transform-produce)模式
追问与易错
追问方向:
- 这个概念在你的项目中是怎么应用的?
- 和相关技术/方案相比有什么优劣?
- 如果出了问题你会怎么排查?
易错点:
- ❌ 只知道概念不知道原理——面试官会追问底层实现
- ❌ 缺乏实际使用经验——结合项目场景回答更有说服力
💡 记忆锚点
Exactly-Once分两层:幂等Producer像快递编号(PID+SeqNum,同一单号不重复签收),事务像银行转账(跨账户要么全成功要么全回滚)。消费端仍需业务幂等兜底——Kafka管到Broker不重复,业务层你自己管。