一个较为健壮的下单方案

一个较为健壮的下单方案

最近在作的一个新项目中,有一个下单兑换的流程。用户的积分能够用来兑换物品。数据库

这个过程当中,须要有几部分的操做:code

  • 积分表扣除积分
  • 兑换表写用户兑换内容、状态
  • 下单
  • 更新用户兑换表为兑换完成状态

这个流程中须要保证扣除积分后,可以为成功为用户下单。一个服务的调用会出现三种状态:成功、失败、超时。超时的状况下,是没法肯定下单是否真正成功的,这时要避免重试时重复下单。为了保证下单流程的健壮性,除了下单接口自己须要作好幂等以外,上层业务自己也须要记录下单过程当中的状态流转,方便进行下单后的逻辑处理,兑换表中须要一个状态字段,可能存在的几种状态为:blog

  • 1:扣除积分,未下单
  • 2:扣除积分,已经下单
  • 3:扣除积分,完成订单
  • 4:下单失败,积分回退

经过数据库的事务,咱们首先须要保证,下单出现非超时错误时,须要回滚下单以前的数据库操做:接口

「 事务

​        扣除积分

​        写兑换表,状态:一、扣除积分、已经下单

」---> 下单失败,回滚事务

下单成功自不用说,将兑换表中状态更新为3便可。当出现下单超时的时候,以上的事务就先不回滚了,经过消息队列来进行下单重试。消息队列的重试,也有可能再次出现超时的状况。队列的重试是有必定的时间间隔的,例如每隔/10/30/60秒重试一次。若是重试3次失败,应该有相应的告警出来,这时候通常是下游的订单服务不可用了。若是在重试下单时,出现了非超时错误,那么这时候应该给用户回退积分,而且将兑换表的状态更新为下单失败,金币回退。队列

重试下单失败-->积分回退

到这里其实已经能够较好地保证用户下单的健壮性的。可是还有一点,在成功下单后,须要更新用户的兑换表到状态3。这个时候有可能会抛出更新数据库表失败的异常,致使实际下单成功,但兑换表状态不一致的状况。解决的办法是当更新兑换表失败抛出异常时,捕获该异常,再利用消息队列发出更新数据库状态的消息,进行更新重试。整个流程以下所示:事务

(完)消息队列

相关文章
相关标签/搜索