已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
【背景】
我做订单履约服务,Kafka 3.5(3 节点),topic order-fulfill 16 分区,实时消费组 8 实例,日均约 4000 万条,消费逻辑是「读 batch → 写 MySQL 8.0 → 提交 offset」。平时正常,但偶发需要重放历史消息做数据补偿:比如下游 DB 主从切换丢了 30 分钟 binlog、或某版本 bug 把一段订单状态写错,需要把过去 30~60 分钟的消息重新消费一遍。
【卡点 / 现象】
seek 到目标 timestamp,结果把整个 group 的 committed offset 拉回去了——实时链路被「倒退」拖回 30 分钟,重复消费了约 12 万条,下游出现重复落库;offsetsForTimes 返回的近似值耦合,定位不准;【已尝试的排查】
offsetsForTimes 按时间戳定位:能定位,但不确定返回的 offset 是「严格 ≥ 目标时间」的近似值,边界 ±1 条不确定;INSERT ... ON DUPLICATE KEY,但「迟到重复」落在去重窗口外时仍会重复执行副作用。【期望得到的答案形态】 希望有做过类似「重放补偿」的同学给具体方案:
offsetsForTimes 的语义、边界 ±1 条怎么兜住),且完全不碰实时 group 的 offset;max.poll.records、DB 连接池怎么配,才能既把 30 分钟消息放完、又不把实时链路和 DB 打垮;我接受「至少一次 + 幂等」的路线,不追求 exactly-once,重点是重放期间实时链路不中断、不重复、不丢失。