业务

电商零碎三大黄金链路为:洽购、购物、退货流程。每一个流程都关涉了大量的分布式服务之间调用,其中最简单外围的就是购物流程,以下是一个简略的模仿业务:

技术

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、领取订单(扣减库存,销售出库)