两种方案:全量异步、半异步。下面分别说明一下两种方案的区别。
全量异步:
1. 前端调用下单接口获取订单id
2. 下单接口构造订单领域对象,并缓存订单id到redis,状态为0(创建中),然后将领域对象通过MQ发送,并返回订单id到前端
3. 订单系统消费异步创建订单的消息,调用库存等服务,如果失败,更新redis状态为-1(并设置错误状态码);如果成功;删除redis记录
4. 前端获取到订单id后,轮询调用订单系统查询订单结果:
4.1 如果redis命中,且为-1,则返回订单创建失败,并返回对应的错误码,并从redis移除。如果是库存不足,则前端调用接口查询实时库存,并进行提示;
4.2 如果redis命中,且为0,则返回订单创建中。前端稍后轮训(重试几次后提示失败)。
4.3 如果redis未命中,则表示订单可能已创建成功(或者redis数据丢失),查询数据库订单数据,如果存在则返回前端订单已创建完成,否则返回创建失败。
5. 前端查询到订单创建成功后,调用获取支付参数接口生成支付订单,进行后续操作。
问题:轮询检查订单是否创建,重试N次后提示失败,有可能服务端会创建成功,造成创建冗余订单的情况。
半异步:
1. 前端调用下单接口获取订单id
2. 下单接口构造订单领域对象(校验订单),调用库存等服务完成下单前确认工作,然后将领域对象通过MQ发送(异步完成订单数据库操作),并返回订单id到前端
3. 订单系统消费异步创建订单的消息,插入订单到数据库
4. 前端获取到订单id后,调用获取支付参数接口生成支付订单,进行后续操作。
5. 如果下单失败,前端根据下单接口返回的错误码进行处理。如果是库存不足,则前端调用接口查询实时库存,并进行提示。
6. 支付服务回调到订单服务后,订单服务的回调处理接口将支付成功的消息投递到MQ
7. 创建订单、订单支付的MQ消息基于RocketMQ的顺序消息,确保订单支付处理前,订单已存在
问题:如果异步插入订单到数据库失败,会阻塞支付成功的消息无法处理。