4. Kafka 生产者可靠性:acks 参数详解(0/1/all)、retries 与 max.in.flight.requests.per.connection、幂等生产者
Kafka 生产者的可靠性核心在于“消息是否真正写入 Broker 并完成持久化”。本章深入剖析三个关键维度:acks 确认机制、重试与并发控制、幂等生产者。理解这些参数是构建高可靠消息管道的基础,也是后续 Outbox 压测调优的前提。
4.1 acks 参数:从“发后即忘”到“全副本确认”
acks 参数控制生产者等待 Broker 确认的级别,直接决定消息的持久化保证与延迟。Kafka 提供三个级别:
| acks 值 | 语义 | 可靠性 | 延迟 | 典型场景 |
|---|---|---|---|---|
0 |
生产者发送后不等待任何确认 | 最低(可能丢消息) | 最低 | 指标采集、日志(可容忍少量丢失) |
1 |
等待 Leader 副本写入本地日志即返回 | 中等(Leader 宕机可能丢消息) | 中等 | 大部分业务系统(默认值) |
all(或 -1) |
等待 Leader 及所有 ISR 内副本全部写入 | 最高(不丢消息) | 最高 | 金融交易、订单、Outbox 消费者 |
关键权衡: 使用
acks=all 时,必须配合 min.insync.replicas 参数(通常设为 2 或 3)来定义“所有副本”的最小数量,否则单副本场景下 acks=all 退化为 acks=1。
4.2 retries 与 max.in.flight.requests.per.connection:重试与乱序控制
当发送失败(如 Leader 选举、网络抖动),生产者会触发重试。但重试可能引入消息乱序,需要与 max.in.flight.requests.per.connection 配合使用。
4.2.1 retries 参数
- 默认值:
Integer.MAX_VALUE(Kafka 3.0+),表示无限重试直到成功或抛出不可恢复异常。 - 重试间隔: 由
retry.backoff.ms控制(默认 100ms)。 - 可重试异常:
LeaderNotAvailableException、NotEnoughReplicasException等;不可重试异常如RecordTooLargeException直接抛出。
4.2.2 max.in.flight.requests.per.connection
该参数控制单个连接上未确认请求的最大数量,直接影响消息顺序:
| 参数值 | 行为 | 顺序保证 | 吞吐量 |
|---|---|---|---|
1 |
严格串行:前一个请求确认后才发下一个 | 严格有序 | 较低 |
5(默认) |
允许 5 个请求在途,重试可能导致后发先到 | 可能乱序 | 较高 |
避坑指南: 如果业务要求严格顺序(如 Outbox 事件按序消费),必须设置
max.in.flight.requests.per.connection=1 且 enable.idempotence=true。否则重试可能导致消息乱序。
4.3 幂等生产者:去重与顺序的基石
幂等生产者(enable.idempotence=true)通过 Producer ID (PID) 和 序列号 (Sequence Number) 机制,确保每条消息在 Broker 端只被写入一次,即使生产者重试也不会产生重复。
4.3.1 核心原理
- PID: 每个生产者实例分配唯一 ID,重启后变更。
- 序列号: 每个 Partition 内从 0 开始单调递增,Broker 按序去重。
- 去重范围: 单 Partition 内、单会话内(PID 不变)。
4.3.2 启用条件与影响
| 条件 | 说明 |
|---|---|
enable.idempotence=true |
必须显式开启 |
acks |
自动升级为 all(即使设为 0/1 也会被覆盖) |
max.in.flight.requests.per.connection |
≤ 5(Kafka 自动保证顺序) |
retries |
自动设为 Integer.MAX_VALUE |
压测建议: 幂等生产者对吞吐量影响极小(通常 < 5%),建议生产环境始终开启。在 Outbox 压测中,开启幂等性可以消除“重复消息”对消费端去重逻辑的干扰,更准确测量端到端延迟。
4.4 参数组合推荐
根据业务可靠性需求,推荐以下参数组合:
| 场景 | acks | enable.idempotence | max.in.flight.requests | retries |
|---|---|---|---|---|
| 最高可靠性(Outbox 推荐) | all | true | 1 | Integer.MAX_VALUE |
| 高吞吐 + 允许少量乱序 | 1 | true | 5 | Integer.MAX_VALUE |
| 极致吞吐(可丢消息) | 0 | false | 5 | 0 |