必须先处理完消息再提交offset,否则会丢消息;需关闭自动提交(enable.auto.commit=false),优先用commitsync()保证可靠性,辅以commitasync()提升吞吐,并结合幂等设计应对重复。

关键在于:先确保消息处理完成,再提交 offset。顺序错了,消息就丢了。
关闭自动提交,由代码控制时机
自动提交靠时间间隔驱动,不等业务逻辑跑完就可能提交,一旦消费者中途崩溃,未处理的消息就永远跳过了。必须显式关掉:
- 配置 enable.auto.commit=false
- 同时建议设置 auto.offset.reset=earliest,避免新消费组启动时漏掉历史消息
同步提交 commitSync():适合对可靠性要求高的场景
调用后会阻塞,直到 Kafka 确认 offset 已写入 __consumer_offsets 主题。它能保证“处理完 → 提交成功 → 下一批拉取”这个链条不中断。
- 推荐在单条或小批量处理后立即调用,比如每处理一条订单就 commitSync()
- 注意:如果提交失败(如网络抖动、Broker 不可用),会抛出异常,需捕获并决定是否重试或告警
- 不要放在循环外统一提交——那样一旦中间某条失败,整批 offset 都无法前进
异步提交 commitAsync():吞吐优先,但要配好回调和重试
不阻塞后续逻辑,适合高吞吐、允许少量重复的业务。但它不保证提交一定成功,失败也不会抛异常。
- 必须提供回调函数,在 onSuccess/onError 中记录日志或触发补偿动作
- 常见陷阱:消费者重启前最后几次异步提交失败,且没做任何兜底,导致 offset 滞后
- 稳妥做法是搭配一次 commitSync() 做最终确认,比如在关闭消费者前调用
结合业务逻辑做幂等与位移粒度控制
offset 是“下一条待消费消息的位置”,不是已处理消息的 ID。提交哪个 offset,决定了重平衡或重启后从哪开始读。
- 如果按批次处理,应提交 最后一条成功处理消息的 offset + 1,不能直接提交 poll 返回的最大 offset
- 例如:poll 出 10 条(offset 100–109),第 105 条处理失败,那只能提交 105(即从 105 重试),而不是 110
- 配合数据库唯一约束、业务单号去重等幂等设计,才能真正扛住重复提交带来的影响
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











