必须禁用自动提交(enable.auto.commit=false),确保提交时机与业务处理结果严格对齐;推荐异步提交commitasync提升吞吐,关闭前同步commitsync兜底,并让异常穿透以触发重试重放。

关键不是“提交动作本身”,而是让提交时机与消息处理结果严格对齐——只有确认消息真正处理成功了,才提交它对应的 offset。
必须禁用自动提交
这是所有手动控制的前提。自动提交会按固定时间间隔(默认 5 秒)提交上一批 poll 到的最大 offset,不管业务逻辑是否执行完、是否出错。
- 在 consumer 配置中显式设置:enable.auto.commit=false
- Spring Boot 中写法示例:spring.kafka.consumer.properties.enable.auto.commit: false
- 不设这一项或设为 true,后续所有手动调用都无效,offset 仍会被后台偷偷提交
处理完成后再批量提交,别单条提交
每处理一条就 commitSync() 一次,性能极差;但完全不控制批次,又可能因崩溃丢失一批 offset。折中做法是:一次 poll 拉取多条 → 全部处理完 → 统一提交这批的最高 offset。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 使用 commitSync() 确保提交成功再继续,适合强一致性场景(如支付、订单)
- 用 commitAsync() 提升吞吐,但需配回调函数捕获失败(比如网络抖动导致提交失败)
- 推荐组合:日常用 commitAsync(),关闭消费者前加一次 commitSync() 做兜底
异常必须穿透,不能静默吞掉
如果业务处理抛异常,你在 @KafkaListener 方法里 try-catch 住却不 throw,Spring Kafka 会认为这条消息“消费成功”,自动推进 position,下次重启就跳过它——消息直接丢失。
- 让异常自然向上抛出,交由 Spring Kafka 的 DefaultErrorHandler 处理
- 默认会重试 9 次(含首次),每次重试前 seek 回原 offset,实现精准重放
- 若需自定义重试策略或死信投递,可配置 SeekToCurrentErrorHandler 或 DeadLetterPublishingRecoverer
注意重平衡时的重复风险
手动提交下,如果 poll 后还没来得及 commit 就触发了 rebalance(比如扩容、机器宕机),新分配到该分区的消费者会从上次已提交位置开始读——导致重复消费。
- 这不是 bug,是 Kafka 的设计机制,需业务层幂等处理(如用订单 ID 去重)
- 可缩短 max.poll.interval.ms(默认 5 分钟),让 Kafka 更快感知消费者卡顿并主动踢出,减少“假存活”带来的重复窗口
- 避免单次 poll 处理耗时过长;大任务拆解、异步化、超时控制都要跟上
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










