现象或背景
在 Kafka 消费端,幂等去重是保障消息不重复处理的关键。我们遇到了一个典型问题:在同一个 InnoDB 事务中写入幂等表与业务表,和两个独立事务(先写幂等表,后写业务表)之间,哪种更容易产生「幂等假阳性」?即幂等记录存在,但业务数据不存在。
我们的 Kafka 版本是 3.5,topic settle-bill 有 24 分区,消费组有 6 实例,max.poll.records=200,enable.auto.commit=false。处理逻辑是先写幂等表,再写业务表,下游 MySQL 8.0.36,innodb_flush_log_at_trx_commit=1。
原理或根因分析
同一个事务(方案 A)
BEGIN;
INSERT INTO t_idempotent (biz_key, msg_id, status) VALUES ('ord_123', 456, 'DONE');
INSERT INTO t_settle_bill (order_id, amount, status) VALUES ('ord_123', 99.9, 'SETTLED');
COMMIT;
优势:事务要么都写,要么都不写,不存在「幂等记录在但业务数据不在」的窗口。
劣势:如果业务表触发行锁等待(比如同一 order_id 的并发更新)或二级索引维护开销大,整个事务持有时间变长。rebalance 时新实例的 SELECT ... FOR UPDATE 会阻塞在行锁上,阻塞时长 = 事务持有时间,不可控。
两个独立事务(方案 B)
-- 事务 1:幂等占位
BEGIN;
INSERT INTO t_idempotent (biz_key, msg_id, status) VALUES ('ord_123', 456, 'PENDING');
COMMIT;
-- 事务 2:业务写入
BEGIN;
INSERT INTO t_settle_bill (order_id, amount, status) VALUES ('ord_123', 99.9, 'SETTLED');
UPDATE t_idempotent SET status = 'DONE' WHERE biz_key = 'ord_123' AND msg_id = 456;
COMMIT;
优势:事务 1 是主键单行 INSERT,持有时间极短(<1ms),rebalance 时新实例几乎不阻塞。
劣势:事务 1 commit 后、事务 2 commit 前 crash → 幂等记录存在(status=PENDING)但业务数据不存在。rebalance 后新实例读到幂等记录,如果去重逻辑只判断"biz_key 存在即跳过",就会静默跳过这条消息——这就是"幂等假阳性"。
具体做法
方案 A 压测结果
- 事务持有时间 P50=2ms / P99=15ms;
- rebalance 时新实例阻塞 P99 ≈ 80ms(等最多 200 行锁释放),可以接受;
- 但如果业务表有并发更新(同一 order_id 的退款/补单),P99 能飙到 400ms+,阻塞窗口不可控。
方案 B 假阳性窗口估算
- 事务 1 commit → 进程 crash → K8s 检测到 Pod 异常 → 拉起新 Pod → 重投 → 读幂等表,这个窗口取决于crash 到新 Pod 就绪的总时间。
- K8s 1.29 maxSurge=1 / maxUnavailable=0 下实测 P99 ≈ 12s(含镜像拉取、JVM 预热、consumer group join)。
- 最坏情况:12s 内新实例读到 PENDING 记录,如果去重逻辑是
WHERE biz_key = ?(不区分 status),PENDING 也会被跳过——假阳性成立。
踩过的坑或反直觉之处
- 事务持有时间对 rebalance 的影响:方案 A 在无并发更新时表现良好,但在有并发更新时,事务持有时间会显著增加,导致 rebalance 阻塞。
- 幂等表和业务表的独立事务带来的风险:即使事务 1 commit 成功,事务 2 的 commit 也可能失败,导致假阳性。
- K8s 的 Pod 拉起时间影响假阳性窗口:Pod 拉起时间长会增加假阳性概率。
结论与可复用清单
- 选择方案时需权衡事务持有时间和 rebalance 阻塞风险:如果业务表并发更新频繁,方案 B 的风险更高。
- 设计去重逻辑时需区分幂等状态:避免仅根据 biz_key 判断是否处理过,应考虑 status 字段。
- 监控和评估假阳性窗口:定期评估 Kafka 消费端的假阳性窗口,确保在可控范围内。
可复用清单:
- 对于高并发场景,优先考虑方案 A,但需监控事务持有时间。
- 对于低并发场景,方案 B 可能更优,但需设计更严格的去重逻辑。
- 定期评估假阳性窗口,确保在可控范围内。
参考资料:
0赞
0收藏
0评论
1浏览