要让Kafka生产者真正“不丢消息”,关键在于acks=all、retries设为最大值、enable.idempotence=true三者协同:acks=all确保ISR全部写入,retries保障失败重试,幂等性防止重试导致重复,缺一不可。

要让 Kafka 生产者真正“不丢消息”,关键不在堆参数,而在于理解重试和确认机制如何协同工作——它们不是孤立配置,而是环环相扣的可靠性链条。
acks 决定“谁说了算”
acks 是生产者端最核心的可靠性开关:
- acks=0:发完就不管,吞吐最高,但网络断、Broker挂、磁盘写失败都可能直接丢消息;
- acks=1:Leader 写成功就返回,适合对延迟敏感且能容忍极小概率丢失的场景(比如日志聚合);
- acks=all(或 -1):必须等所有 ISR 副本同步完成才确认,这是防止 Leader 故障导致数据丢失的底线配置。
注意:acks=all 不等于“绝对不丢”——它依赖于 ISR 列表健康。若 min.insync.replicas=2,而当前 ISR 只剩 1 个副本,那即使设了 acks=all,也会直接报错拒绝写入,避免降级为弱一致性。
重试不是越多越好,而是要“有边界地坚持”
retries 控制重试次数,但它必须和两个时间参数配合使用:
- retry.backoff.ms:每次重试前等待多久,默认 100ms,太短会加剧 Broker 压力,建议设为 300–500ms;
- delivery.timeout.ms:整个发送过程的总时限(含重试),默认 120 秒,必须大于 retries × retry.backoff.ms,否则重试还没跑完就被强制终止。
常见误区是只调大 retries 却忽略 delivery.timeout.ms,结果重试被截断,消息静默失败。推荐组合:retries=2147483647(Integer.MAX_VALUE) + delivery.timeout.ms=120000 + retry.backoff.ms=500,既保证尽力而为,又不失控。
幂等性是重试的安全护栏
开启重试后,网络超时、Leader 切换等可重试异常会导致同一条消息被多次尝试发送——没有幂等性,就会在分区里写入重复记录。
- 启用幂等只需加一行:
enable.idempotence=true; - 它要求同时满足:
acks=all、retries > 0、max.in.flight.requests.per.connection ≤ 5(默认值即满足); - 底层靠 PID + 序列号实现去重,对业务透明,不改变消息顺序,也不增加额外开发成本。
幂等性不能解决消费者侧重复,但它从源头掐断了“生产即重复”的可能性,是高可靠链路的标配。
同步 vs 异步:别让错误处理方式毁掉可靠性
无论用哪种发送方式,都必须显式处理结果:
-
同步发送:调用
send(record).get(),阻塞等待响应,适合调试或低吞吐关键路径,但性能差; -
异步发送:传入
Callback,在onCompletion()中判断exception == null,失败时需记录日志、告警甚至落库重发——漏掉回调处理,等于没配 acks。
切忌“调用 send() 就完事”,未捕获异常或忽略回调失败,会让所有可靠性配置形同虚设。










