电商物流综合仿真系统攻略「电商怎么做」
今天给大家普及一下电商物流综合仿真系统攻略「电商怎么做」相关知识,最近很多在问电商物流综合仿真系统攻略「电商怎么做」,希望能帮助到您。
作者:startshineye
出处:https://segmentfault.com/a/1190000037586408
业务电商系统三大黄金链路为:采购、购物、退货流程。每一个流程都牵涉了大量的分布式服务之间调用,其中最复杂核心的就是购物流程,以下是一个简单的模拟业务:
技术1.分布式微服务调用2.分布式事务2.1 分布式事务常见方案:(1) XA分布式事务:单系统多数据库
(2) TCC分布式事务:服务链式调用、解决大多数分布式事务场景,主要用于同步实时结果返回场景。 注意:对于bytetcc简化版本主要针对于一个接口情况,简化版本通过不同注解代表的不同方法表明confirm、cancel、try,针对于多个接口都需要满足tcc事务的话,需要使用非简化版本的tcc,非简化版本使用不同的类实例实现的同一接口方法表示不同的conform、cancel、try。
(3) 可靠消息最终一致性:多用于耗时、异步 并且消息必须执行成功的场景
(4) 最大努力通知方案:多用于耗时、异步 并且消息可有可无的场景;比如:短信,
分布式事务混合使用注意:在很多业务场景下,我们的分布式事务可能是多个方案一同使用,需要将多个方案的代码分离,避免各种方案事务干扰。可以将接口调用拆分成多个接口。
2.2 分布式事务运用创建订单场景(锁定库存)(1) tcc分布式事务:订单的创建(订单创建主要是:库存中心、调度中心、wms中心锁定库存;可销售库存减1、锁定库存 1)中订单中心跟库存中心之间需要实时同步执行(对应上图5.1-5.5);订单中心出错,库存中心不能执行;订单中心成功,库存中心出错,库存中心本地事务回滚,同时通知订单中心之前操作进行cancel。当两中心都成功时候,才发送消息到MQ,通知调度中心、WMS中心异步进行库存锁定、出库调度。
(2)可靠消息最终一致性分布式事务:订单创建后通知调度中心、wms中心出库调度和库存锁定(对应上图5.6-5.8)使用可靠消息最终一致性方案,如果前面TCC分布式事务都执行成功的话,发送“待确认”消息给可靠消息服务;可靠消息服务投递消息到MQ,调度中心消费消息直至成功。
1、先执行第一步创建订单,第一步执行成功后再执行第二步:异步化锁定库存,出库调度。库存中心会发消息给可靠消息服务,可靠消息保证消息一定成功消费以及成功处理。
2、调度外呼接口服务在正确执行完步骤之后会告知可靠消息服务,然后可靠消息服务设置消息状态为已完成。
3、调度中心跟wms中心使用tcc分布式使用,保证一同成功/失败。
支付订单场景(扣减库存)支付订单的入口,我们从订单中中心更改订单中状态为已支付开始;更改订单状态跟库存中心扣减库存需要绑定tcc。
分析以上图我们知道:
1、支付订单成功之后,通知订单中心;订单中心更新状态,订单中心调用库存中心扣减库存需要实时保持事务一致性,使用tcc分布式事务。如果这一步失败的话,后面所有的 东西都不要去执行。(订单中心修改订单状态和库存中心扣减库存同步保证一致性,一同成功/失败---图:9.1-9.3)
2、如果1执行成功的话,订单中心需要通知库存中心投递消息到可靠消息服务中去,然后基于可靠消息最终一致性方案实现,库存扣减跟销售出库。
订单中心可以直接通知可靠消息服务:调度出库;然后调度外呼服务收到之后去调用调度服务去调度出库,然后调度中心调用wms中心:创建出库单。
3、如果2执行成功之后,订单中心直接通知可靠消息服务增加回来积分消息,会员服务消费消息,然后增加本地数据库积分(这个也是可靠消息最终一致性方案)。
步骤3也执行完毕的话,订单中心消息需要发送消息,订单中心直接发送消息到mq,然后最大努力通知服务消费消息,然后存储消息到本地数据库,完成消息的发送。
tcc分布式事务总结tcc分布式事务的灵活应用是保障分布式事务简洁、高效条件;需要建立在对业务模块比较很熟的经验之上。
1、bytetcc简化模式跟非简化模式何时使用?
对于bytetcc简化版本主要针对于一个接口情况,简化版本通过不同注解代表的不同方法表明confirm、cancel、try,针对于多个接口都需要满足tcc事务的话,需要使用非简化版本的tcc,非简化版本使用不同的类实例实现的同一接口方法表示不同的conform、cancel、try。
2、业务中如何分辨tcc中的try,confirm,cancel?
tcc需要灵活使用,针对于同一个方法有前后两种状态的时候,一个方法里面做try,confirm,cancel逻辑判断
如果针对于一个业务多个方法时候,tcc的三步骤会贯穿各个方法中(先执行的业务方法当作try来预备资源和cancel释放资源,对于后执行的业务方法当作confirm来确认资源),针对于只有单个步骤的操作,我们的confirm有时候可能直接省略;try就是执行目标操作,cancel就是撤销目标操作(比如会员积分更改)
针对于有转账场景:
转账有转账人,被转账人之分;目标结果就是confirm需要实现的结果;
try阶段:转账人扣减金额到锁定金额
confirm阶段:转账人锁定金额扣减添加到被转账人金额
cancel阶段:cancel是对资源释放,对try的反向操作,此时执行:转账人金额从锁定金额变化到转账人金额。
电商中库存锁定场景:
在提交订单时候,库存中心的库存会变化,可销售库存减少,锁定库存增加,最后执行sql更新操作。针对于这种业务场景,目标结果业务是一步到位的,所以我们需要在这个方法里面进行tcc操作。
提交订单简化主要任务是:可销售库存减、锁定库存加;所以tcc最后目标是锁定库存加;因为
try阶段:可销售库存减
cancel阶段:可销售库存加
confirm阶段:锁定库存加
/** * 更新销售库存: * try阶段:销售存库减 * cancel阶段:销售库存加 * @throws Exception */@Overrideprotected void updateSaleStockNum() throws Exception {//订单的每一个商品的可销售库存减1 for (商品 do:商品列表) { System.out.println("执行try操作:" tccType); do.setSaleStockNum(do.getSaleStockNum()-购买数量); }else if(TCCType.CANCEL.equals(tccType)){System.out.println("执行cancel操作:" tccType); do.setSaleStockNum(do.getSaleStockNum() 购买数量); }}}/** * 更新锁定库存: * confirm 锁定库存加1 * @throws Exception */@Overrideprotected void updateLockedNum() throws Exception {//更新锁定库存 for (商品 do:商品列表) { if(TCCType.CONFIRM.equals(tccType)){System.out.println("执行confirm操作:" tccType);do.setLockedStockNum(do.getSaleStockNum() 购买数量); } }}支付订单:
支付中心支付完毕之后通知订单中心发起支付完成通知,订单中心会同步通过tcc通知库存中心扣减库存:目标锁定库存减、已销售库存加。所以我们把目标的第一步当作tcc的try阶段,confirm阶段在第二步。
@Overrideprotected void updateLockedStockNum() throws Exception {for (商品 do:商品列表) { if(TCCType.TRY.equals(tccType)){do.setLockedStockNum(goodsStockDO.getLockedStockNum()-购买数量); }else if(TCCType.CANCEL.equals(tccType)){do.setLockedStockNum(do.getLockedStockNum() 购买数量); }}}@Overrideprotected void updateSaledStockNum() throws Exception { for(商品 do:商品列表){ if(TCCType.CONFIRM.equals(tccType)){ do.setSaledStockNum(do.getSaledStockNum() 购买数量); } }}会员中心:
在购物流程中,订单支付时候,订单中心更改订单状态、库存中心更改库存、会员中心增加会员积分我们当成一个tcc分布式事务。会员中的两个操作更新积分和撤销积分已经对外提供接口,所以我们直接可以在tcc的controller外部调用。
@RestController@Compensable(interfaceClass = MembershipApi.class,simplified = true)public class MembershipTccService implements MembershipTccApi { /** * 通知会员中心,“支付订单”事件发生了 * @param userAccountId 用户账号id * @param totalOrderAmount 订单总金额 * @return 处理结果 */ @Override @Transactional public Boolean payOrder(@PathVariable("userAccountId") Long userAccountId, @RequestParam("totalOrderAmount") Double totalOrderAmount) throws Exception{ membershipExecutor.do(userAccountId,totalOrderAmount); return true; }@CompensableConfirm @Transactional public Boolean confirmPayOrder(@PathVariable("userAccountId") Long userAccountId, @RequestParam("totalOrderAmount") Double totalOrderAmount) throws Exception{return true; }@CompensableCancel @Transactional public Boolean cancelPayOrder(@PathVariable("userAccountId") Long userAccountId, @RequestParam("totalOrderAmount") Double totalOrderAmount) throws Exception{membershipExecutor.undo(userAccountId,totalOrderAmount); return true; }}2.分布式幂等性购物流程主要包含两个子流程:1、创建订单order流程(锁定库存) 2、支付订单(扣减库存,销售出库)
作者:startshineye
出处:https://segmentfault.com/a/1190000037586408