0%

Tom 商店-避免重复下单策略

电子交易的一个很基本的问题,就是避免用户下重复订单。用户明明想买一次,结果一看下了两个单。从技术上看,这是一个分布式一致性问题。但实际上,技术无法 100% 解决这类问题。

1. 用户下单流程

我们先来看看用户下单的简要流程:

  • 加购:用户可以选择直接购买商品,也可以先加入购物车
  • 结算/下单:购物车页面点击结算进入结算页面,去支付这一步就会生成一个订单,然后进入付款页面

我们可以看到,下单是发生在结算之后,下单之后,会生成唯一的订单号,接下来,客户端需要用这个订单号去完成支付。

那接下来先看看,为什么发生重复下单?

2. 为什么会重复下单

为什么会重复下单,对于订单服务而言,就是接到了多个下单的请求,原因可能有很多,最常见的是这两种:

  • 用户重复提交
  • 网络原因导致的超时重试

重复下单原因

3. 如何防止重复下单

防止用户提交,最常规的做法,就是客户端点击下单之后,在收到服务端响应之前,按钮置灰。

当然,防止重复下单,肯定不能只依靠客户端,可能会因为一些网络的抖动,导致仍然有重复的请求到达服务端,所以还是要在服务端做防重/幂等的处理。

支付下单流程

上图为 Tom 商店支付下单流程。在创建订单之前会以 UID 作为 key 加分布式锁,加锁失败则直接提示异常。接着会校验购物车商品是否已经发生变化,如若购物车商品发生变化则触发重复提交异常,提示用户购物车商品发生变化并跳转回购物车页面。最后在创建订单基本信息之后则需要删除购物车已购的商品,以此确保 去支付过程中可以触发 购物车商品未变化? 的条件检验,加强防止多次提交导致的重复下单。

如果 UID 分布式锁过期时间设置的过短而创建订单流程耗时过长,如果此时还未删除购物车已购商品而 UID 分布式锁就已经过期失效,此时有请求进来则可能产生重复下单。因此我们可以将尽量将 UID 分布式锁过期时间设置相对较长一点,减少锁过期自动失效的发生。

------ 本文结束------