这类问题我又碰上了一次。异步批量任务完成后回调业务接口,网络抖动导致同一事件投递三次,接口没有幂等,结果创建了三份相同的日报,运营早上看到三条一样的推送。

第一反应是「处理超时太短 上游判定失败后重投」,验证下来不成立。

原因不止一个,得分开看。回调是至少一次投递 不保证唯一;业务侧没有记录事件 id;多实例部署时并发处理同一事件。

上来先确认事件里的唯一标识字段

python -c "import json;e=json.load(open('event.json'));print(list(e.keys()))"

随后用事件 id 建唯一索引落库

python -c "print('unique index on event_id')"

接着处理前先抢占 抢占失败直接返回 200

python callback.py --idempotent --store redis

剩下的就是用重放脚本验证只消费一次

python replay.py --event event.json --times 3

怎么算真的好了,看的是同一批现象。重放三次只产生一份日报,接口三次都返回 200,缓存里能看到事件 id 的键。

回调永远按至少一次设计,幂等键要和业务写入放在同一事务里,先查后写挡不住并发。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189