跳到主要内容
弗美科技
技术分享

接口幂等,重复提交那 3 笔订单

一个下单接口,同一笔订单被创建了 3 次,原因是前端超时重试,后端每次都当新请求。没上分布式锁,先在请求头里加了一个客户端生成的 request_id,服务端用它做唯一索引,重复的返回第一次结果。顺带把超时时间从 3 秒调到 8 秒,重试反而少了。

2022年9月16日幂等接口设计踩坑记录

9 月 16 号上午,客服转来三条几乎一样的订单,同一个用户、同一件商品、时间差不到 2 秒。金额一样,收货地址一样,只有订单号不同。

为什么会三次

前端设了 3 秒超时,网络稍慢没等到响应就自动重试,最多重试 2 次。后端下单接口没有任何去重,收到一次插一条。三次全成功了。

这跟之前积分那次不一样:那次是用户手动点,这次是程序自己点的,人根本不知道。

幂等键放在哪

讨论过用用户 id 加商品 id 加时间戳,但时间戳一变就不算重复,等于没防。最后用客户端生成的 request_id:下单页一加载就生成一个 uuid,跟着这次提交一起发,重试时还是同一个。

服务端拿 request_id 在订单表上建唯一索引。重复进来插不进去,捕获冲突后不报错,把已有那条订单查出来原样返回。前端拿到的是同一个订单号,不会以为失败再试。

关键还是那句:重复请求返回原结果,别返回错误。

顺手改的两处

  • 前端超时从 3 秒调到 8 秒。多数「超时」其实只是慢,不是没到。调完之后重试次数肉眼可见地少了。
  • 重试只针对明确的网络错误,5xx 和业务错误不重试。第一版没分,业务上提示「库存不足」也重试了两次,白耗。

补数据

已经生成的 3 笔,留 1 笔,另外 2 笔走取消流程,不硬删,取消记录里写明「重复提交合并」。支付那边只扣了 1 笔,没造成重复扣款,这是不幸中的万幸。

导出一张明细给客服,一共 7 列,让他们照着跟用户解释。

后来

把「所有创建类接口」过了一遍,一共 9 个,逐个看有没有幂等键。有 4 个当时没出过问题,也补了。评审单里加了一行:这个接口被调两次会怎样。

那三张订单截图没删,放在内部文档的「重复」那一节。跟《两小时》挨着。

商务咨询 · 免费初步沟通

需要针对你的场景给个建议?

把业务背景和当前系统情况告诉我们,我们会给出可执行的思路。

在线留言

周一至周五 9:00–18:00 · 工作日 9:00–18:00 响应,留言会在一个工作日内回复。

商务微信
商务微信二维码

扫一扫,加商务微信咨询服务与方案报价

或填写需求表单