# consumer.properties
enable.auto.commit=false
# 处理完成后
consumer.commitSync(Collections.singletonMap(tp,
new OffsetAndMetadata(record.offset() + 1)));
发布重启后二十分钟,对账发现 12.4 万条订单被处理了两遍,消费日志里同一 offset 出现两次,位点从 8812300 跳回 8691000。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:消费者在 rebalance 前把位点异步提交出去,实际处理还没做完,新实例从已提交位点之后开始拉,旧实例手上那批又被重新投递。enable.auto.commit 打开时提交时机完全由客户端定时器决定。
「Kafka 位点回退」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
处理上按这个顺序:关掉自动提交 改成处理成功后同步提交;实现 ConsumerRebalanceListener 在分区被回收前提交已完成位点;业务侧按订单号加唯一键 兜住重复写入;重放这段区间核对订单状态表条数。
确认没问题再收工,重放同一段 12 万条消息 订单状态表新增行数为 0 位点单调递增不回退。
