实际项目中用到的分布式事务
1.本地消息表+定时任务
-
业务场景:
创建完订单,进行支付,订单和支付属于不同的模块,需要用分布式事务进行处理。
-
基本流程:
支付模块相当于生产者,订单模块相当于消费者。支付模块中有一张异步通知表,订单模块有一张支付结果通知表。支付完成时,异步通知表增加一条数据,同时异步回调订单模块的支付通知接口,支付结果通知表中添加一条数据,并更新订单表相关的状态。如果回调失败,则进行重试,回调的接口必须满足幂等性。
-
具体流程:
涉及到以下几张表的关键字段:
payment表:
列名 描述 notify_url 支付结果异步通知url status 支付状态 0:等待支付,1:成功,2:失败 payment_result表:
列名 描述 notify_status 结果通知状态 1:未通知,2:已成功通知 notify_schedule表:
列名 描述 next_notify_time 下次通知时间 notify_count 通知次数 notify_status 通知状态 1:已通知,2:通知失败,3:通知成功 notify_content 通知内容(异步通知订单模块接口的请求参数) order_payment_notify表:
列名 描述 status 支付结果 1:成功 10:失败 order表:
列名 描述 order_status 订单状态 1:新增,2:已支付,3:处理中,4:已完成,5:已取消 payment_status 支付状态 0:未支付,1:正在支付,2:支付完成。3:支付失败 -
创建完订单,order_status=1,payment_status=0;
-
支付模块进行支付,payment表中添加数据,支付成功后,payment表中status=1,payment_result表中添加数据,notify_status=1;
-
准备通知订单模块更新数据,
- notify_schedule表中添加数据,notify_status=1,
- 异步回调订单模块的支付通知接口,
- order_payment_notify表中添加数据,order表更新数据;
如果通知成功,
- 更新payment_result表中的数据,notify_status=2;
- notify_schedule表中notify_status=3,
- 订单模块中order_payment_notify表中status=1,
- order表中order_status=2,payment_status=2;
如果通知失败,通过定时任务进行重试,更新notify_schedule表中的数据。
-
-
相关代码:
-
支付模块:
public boolean notifyResult() { //1.notify_schedule表中添加数据,notify_status=1 notifyScheduleMapper.insertSelective(notify); //2.异步回调订单模块的支付通知接口 JSONObject json = SoaHelper.postRequest(httpExcutor, message.getNotifyUrl(), jsonNotify, JSONObject.class, headers); //3.通知成功 if(json != null){ //payment_result表中添加数据 paymentResultMapper.updateNotifyStatus(paymentId); //更新notify_schedule表中的数据,notify_status=3 notifyScheduleMapper.updateByPrimaryKeySelective(notify); }else{ //4.通知失败 //更新notify_schedule表中的数据,notify_count+=1,更新next_notify_time,等待定时任务调用,再次执行 //如果通知次数notify_count>9,设置为通知状态失败notify_status=2 notifyScheduleMapper.updateByPrimaryKeySelective(notify); } return true; }sfsadfa
public void notifyPendingResultJob() { //获取所有等待通知的记录:3天内,通知次数小于10,通知状态等于1 List<NotifySchedule> lstNotify = getAllPendingResult(); for(NotifySchedule notify : lstNotify){ //调用上面的通知接口 notifyResult(); } }
-
订单模块:
public boolean onPaymentNotify(OrderPaymentNotify notify) { //1.同一支付结果的重复通知返回成功,保证幂等性 if (orderPaymentService.isRepeatNotify(notify.getPlatformId(), notify.getPaymentCode())) { return true; } //2.order_payment_notify表添加记录,支付成功status=1 orderPaymentService.addOrderPaymentNotify(notify); //3.更新order主表支付状态payment_status=2 updatePaymentStatus(order, PaymentStatus.PS_PAY_COMPLETED.CODE, operator, DESC); //4.更新order主表订单主状态order_status=2 updateOrderStatus(order, OrderStatus.OS_HAD_PAY.CODE, operator, DESC); //后续操作,生产券码,扣减库存等等 ...... return true; }
-