这是 Kafka 最值得你建立的第二个大心智。
Kafka 会保留消息,消费进度和消息保留是两回事。
也就是说:
- 你消费过了,不代表消息立刻删除
- 只要 retention 没过,别的 group 还能读
- 你自己把 offset 倒回去,也能重读
消息保留(retention)
≠
消息已被某个 group 消费#retention 是什么
Kafka 常见保留策略包括:
- 按时间保留
- 按大小保留
- 对部分 topic 开启 compaction(保留同 key 的最新值)
这意味着 Kafka 很适合做:
- 事件溯源
- 数据重放
- 故障恢复后补算
- 下游新系统晚到后补消费
#为什么会重复消费
重复并不是 Kafka “坏了”,而是它的设计现实。
最常见的重复来源:
- consumer 处理成功了,但还没来得及 commit 就宕机
- producer 因网络抖动重试
- rebalance 期间分区被重新分配
- 你主动回放老 offset
所以你必须把这句话刻进脑子:
Kafka 的正确姿势不是幻想“永不重复”,而是接受“可能重复”,然后把消费端做成幂等。
例如:
- 用业务主键去重
- 数据库写入做唯一约束
- 外部副作用做幂等检查
#exactly-once 怎么理解才不误解
Kafka 确实支持更强语义,但别神话。
更稳妥的理解是:
- Kafka 可以在特定条件下提供 exactly-once processing 能力
- 尤其是在 Kafka 内部读写链路、事务 producer、
read_committed等配合时 - 但“业务世界绝对不会重复”不是靠一句 exactly-once 自动实现的
如果你还要写数据库、调第三方支付、发短信:
最终仍要靠业务幂等设计兜底。