开放问答
MirrorMaker 2 跨集群复制后消费端 offset 重置,传统基于 offset 的幂等去重失效怎么兜底?
该问题的正文、回答与评论。
提问者 江墨白-895 · 状态 open
KafkaMirrorMaker2幂等消息中间件分布式一致性
【背景】
我们做异地多活架构:机房 A 的 Kafka 3.5(KRaft,3 broker,topic trade-event 32 分区)通过 MirrorMaker 2(mm2 2.7)单向复制到机房 B 的 Kafka 3.5(3 broker,topic 同名同分区数)。机房 B 的消费组 b-trade-consumer(6 实例)消费的是复制过来的副本,业务逻辑是写本地 PostgreSQL 15 + 更新 Redis 7 缓存。
【现象与卡点】
MM2 的 offset 映射机制决定了:B 集群中每条消息的 offset 与 A 集群并非一一对应(MM2 内部维护 mirror-offset 映射,但消费端只看到 B 集群自己的 offset 序列)。我们原来的幂等方案是「记录每个 partition 的 lastProcessedOffset,新消息 offset ≤ lastProcessedOffset 则跳过」,这在单集群内有效,但切流到 B 集群后,同一个业务事件在 B 集群的 offset 可能与 A 完全不同,导致:
- 切流前后同一事件被重复处理(offset 比较失效);
- 如果业务事件本身有唯一 ID(
biz_event_id),但消费端没有落库去重,仅靠 offset 判断,切流窗口内必然重复写入。
【已尝试的排查】
- 改用
message.timestamp + partition做去重键 → 发现 MM2 复制时保留了原始 timestamp,但同一 partition 内不同消息可能 timestamp 相同(批量写入),仍会漏判; - 在消费端加一张
consumed_events(biz_event_id, consumed_at)表,用唯一索引去重 → 功能上可行,但 6 实例 × 32 分区高并发下,这张表的写入 QPS 接近 12 万,PostgreSQL 单表已经出现 200ms+ 的锁等待; - 考虑用 Redis SETNX(
event:{biz_event_id},TTL 7 天)做前置去重 → 担心 Redis 故障时退化为无去重,且 7 天 TTL 是否够用没有数据支撑。
【期望得到的答案形态】
- 在 MM2 跨集群复制场景下,社区里生产环境验证过的消费端幂等方案是什么?(不局限于"用业务主键去重"这种泛泛而谈,想听具体的表结构 / 数据结构 / 过期策略 / 故障降级路径)
- 高并发下幂等表(或等价结构)的写入瓶颈,大家是怎么解的?分库分表?按
biz_event_id哈希分片?还是换存储(如 RocksDB 嵌入式)? - 切流(A→B 或 B→A)窗口内,有没有"双写去重"的过渡方案,保证不丢不重?
欢迎贴你们的实际配置、表 DDL、压测数据,越具体越好。
已采纳
回答者
回答正文
评论
暂无评论。