使用最终一致性思想解决分布式事务
//需求,下单流程需要调用库存服务扣减库存,调用积分服务扣减积分,调用奖励金服务扣减奖励金,调用优惠券服务使用优惠券,如果调用其中一个服务挂了,如何处理 分布式事务 //伪代码 @Transactional public ShopOrderMast creatOrderMast(OrderResq resq){ boolean flgScore=false;//是否扣减积分成功 boolean flgBlance=false;//是否使用奖励金抵扣成功 boolean flgCoupon=false;//是否成功使用优惠券 List<Item> list=null;//成功扣减商品的集合 try { //调用库存服务扣减方法 stockResp=A.subStock(itemList); if(stockResp==null || !stockResp.isSuccess){//或者有些公司封装成的是状态码 throw ex;//自己定义的异常 }else { list=stockResp.getList();//获取扣减成功的商品集合 } //调用积分服务扣减积分 ScoreResp=B.subScore(scoreList); if(ScoreResp==null || !ScoreResp.isSuccess){//或者有些公司封装成的是状态码 throw ex;//自己定义的异常 }else { flgScore=true;//积分扣减成功 } //奖励金服务抵扣 blanceResp=C.subBlance(balanceList); if(blanceResp==null || !blanceResp.isSuccess){//或者有些公司封装成的是状态码 throw ex;//自己定义的异常 }else { flgBlance=true;//奖励金扣减成功 } //调用优惠券服务 couponResp=D.useCoupon(coupOnId); if(couponResp==null || !couponResp.isSuccess){//或者有些公司封装成的是状态码 throw ex;//自己定义的异常 }else { flgCoupon=true;//成功使用优惠券 } } catch (BaseException e) { if(CommonUtil.isNotNull(list)){//如果list有数据,证明这些库存扣减成功了,需要回滚 addStockResp=A.addStock(list);//调用库存回滚方法 if(addStockResp==null || !addStockResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addStockResp)); } } if(flgScore){//积分扣减成功了 addScoreResp=B.addScore(score);//调用积分回滚方法 if(addScoreResp==null || !addScoreResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(score),JSON.toJSONString(addScoreResp)); } } if(flgBlance){//奖励金扣减成功了 addBlanceResp=C.addStock(blancelist);//调用奖励金回滚方法 if(addBlanceResp==null || !addBlanceResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addBlanceResp)); } } if(flgCoupon){ //如果优惠券使用成功了 addCouponResp=D.addStock(coupOnId);//调用优惠券回滚 if(addCouponResp==null || !addCouponResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addCouponResp)); } } throw e; } catch (Exception ex) { if(CommonUtil.isNotNull(list)){//如果list有数据,证明这些库存扣减成功了,需要回滚 addStockResp=A.addStock(list);//调用库存回滚方法 if(addStockResp==null || !addStockResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addStockResp)); } } if(flgScore){//积分扣减成功了 addScoreResp=B.addScore(score);//调用积分回滚方法 if(addScoreResp==null || !addScoreResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(score),JSON.toJSONString(addScoreResp)); } } if(flgBlance){//奖励金扣减成功了 addBlanceResp=C.addStock(blancelist);//调用奖励金回滚方法 if(addBlanceResp==null || !addBlanceResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addBlanceResp)); } } if(flgCoupon){ //如果优惠券使用成功了 addCouponResp=D.addStock(coupOnId);//调用优惠券回滚 if(addCouponResp==null || !addCouponResp.isSuccess){ //此时回滚还是失败的话,将记录存到日志表 logService.addLogData(requestUrl,JSON.toJSONString(list),JSON.toJSONString(addCouponResp)); } } throw new BaseException(ex.getMessage(), ex); } }
//每天观察日志表看看有没异常,调用哪个方法,哪个接口出了异常,最后人工介入
日志表设计如下: