后端每次下单生成新 ID 时,重复请求如何保持相同幂等 ID?

考查重点:首次操作令牌与订单绑定。首次下单前给操作令牌或由稳定业务键查已有记录,重试带同令牌,真正创建订单时绑定唯一约束

本题目录

参考答案

核心回答

如果后端在每次收到下单请求时才生成全新的订单号,而请求又不携带任何稳定操作标识,服务端无法仅凭这些新订单号判断哪些请求属于重试。需要把“识别一次购买意图”前置:首次下单前获取操作令牌,或由客户端生成并保存幂等键,后续重试一直携带它。

订单号可以在真正创建订单时生成,但应与稳定幂等键建立唯一绑定。这样订单号属于结果,幂等键属于产生这个结果的业务动作,两者不会相互循环依赖。

一条完整处理流程

  1. 用户开始一次确认购买流程,得到 operationToken;相同流程超时重试时复用,明确开启下一次购买才生成新令牌。
  2. 服务端校验身份、令牌适用范围与参数,将 (userId, operationToken) 作为数据库唯一键。
  3. 在同一事务中建立幂等记录、生成订单、保存订单结果;并发重复插入由唯一约束裁决,不能只先查询“没有记录”就分别创建。
  4. 首次响应丢失后,重试查询这个键的处理结果,返回同一个订单。处理中、可重试失败与已完成要分别表达。

如果幂等记录和业务写入位于不同存储,仍存在一边成功一边失败的窗口,需要重新设计事务边界或采用可靠事件,而不是单独加一个 Redis SET NX 就结束。

为什么其他替代方案不够

仅按请求参数哈希去重,会把用户合法的两次相同购买误判成重复。仅在前端禁用按钮挡不住网络重试和并发调用。每次返回一个新的令牌,又会让下一次重试变成全新操作。

订单创建后发生支付或退款,可以使用对应业务动作自己的稳定标识继续做幂等。创建订单的令牌不应被无条件复用于所有后续动作。

对应教程

参考资料

  • 国内:阿里云:使用ClientToken保证幂等:采用首次建立稳定操作令牌、跨重试复用并返回已有结果的契约,解释订单号尚未生成时如何识别同一次意图。
  • 国内:阿里云:消息幂等:采用业务唯一标识处理重复发送与重复投递,区分消息标识和业务动作。
  • 国内:Leo(编程导航):接口幂等性:借鉴前置操作令牌和唯一索引识别重复的做法,说明仅先查询不存在不能裁决并发下单。
  • 国内:JavaGuide:分布式锁:采用数据库唯一约束可独立保护业务条件的分析,说明订单创建要由唯一键与本地事务裁决并发。
  • 国外:AWS:Making retries safe with idempotent APIs:采用请求标识记录与业务变更必须原子提交的约束,解释幂等记录、订单与结果应绑定在同一事务中。
  • 国外:Stripe:Idempotent requests:核对相同幂等键重试可返回已保存结果的契约,解释首次响应丢失后如何取得已有订单结果。

相关面经

1 篇

百度

Go 后端开发工程师
二面
查看原面经 →
追问
如果每次下单都是后端生成一个新的 ID,那么重复请求的时候怎么保证还是同一个 ID?

相关题目

4 题