客户端提交订单超时后重发,请求头里的 Idempotency-Key 没变,服务端还是建了两条订单,两条的创建时间差 400 毫秒。乍看像缓存或者权限的锅,追下去往往不是。

INSERT INTO idempotency(key, status) VALUES (%s, 'processing')
ON CONFLICT (key) DO NOTHING RETURNING id;

追下去是这么回事:幂等键只在前端生成,服务端没落库也没加唯一约束,两个请求并发进来都查不到已有记录,各自往下走。检查和处理之间没有原子性,中间只要有一个请求没提交事务,另一个就看不见。

「幂等键」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。

具体做法是,把 Idempotency-Key 和业务结果一起写进一张幂等表 键上加唯一索引;处理前先插入幂等记录 插入冲突就直接返回上一次的结果;幂等记录设过期时间 别无限增长 过期时间要覆盖客户端的重试窗口;把超时重发写进自动化用例 每次发版跑一遍。

验收就看一点,用同一个键连发十次 数据库里只有一条订单 十次响应里的订单号完全一致。

作者 9823189