老生常谈的问题:电商业务中如何防止重复下单?( 二 )


大概的逻辑:

  • 就是以requestId为维度 , 进行加锁 , 如果获取锁失败 , 就抛一个自定义的重复下单异常 。
  • 如果获取到锁 , 先check一下 , 是否已经下单 , 为了提高性能 , 下单完成后 , 也把下单的结果放在Redis缓存里 。

老生常谈的问题:电商业务中如何防止重复下单?

文章插图
redis防重逻辑
大概的代码如下:
public PlaceOrderResVO placeOrder(PlaceOrderReqVO reqVO) {//加锁RLock orderLock = redissonClient.getLock(RedisConstant.PLACE_ORDER_LOCK_KEY + reqVO.getRequestId());//获取锁失败 , 抛出重复下单异常if(orderLock.isExistes){throw new OrderRepeatException();}// 加锁orderLock.lock();try {//检查是否已经下单RBucket<PlaceOrderResVO> orderCache = redissonClient.getBucket(RedisConstant.PLACE_ORDER_LOCK_KEY+reqVO.getRequestId());if(orderCache.isExistes){return orderCache.get();}//下单业务逻辑……//落库//订单落库Order order = orderMapper.saveOrder(orderDO);……//缓存结果orderCache.put(resVO);return resVO;}} catch (Exception e) {//……} finally {orderLock.unlock();}return resVO;}这里再说明一下:
  • 为什么获取不到锁的时候要抛异常呢?
因为下单里面其实还有一些其它的业务流程 , 比如锁库存、清优惠券……而此时 , 获取到锁的请求的下单流程还没有结束 , 下单的结果还获取不到 , 没法完成响应 , 也就没办法做幂等 。
客户端 , 也可以根据响应的状态码 , 进行特殊处理 , 比如这个异常先不提示 , 但是允许用户再次点击下单按钮 , 来提升用户的体验 。
原文链接:
https://mp.weixin.qq.com/s/Dc_4taB6Boojdw_0mngroQ
作者:三分恶

【老生常谈的问题:电商业务中如何防止重复下单?】


推荐阅读