00:00
前面呢,我们给大家演示了一下,我们调用远程锁库存服务,一旦我们这个库存锁定失败以后,我们订单的整个回滚,我们是通过这个异常机制,只要锁库存服务,库存锁定失败,它会给我们返回失败的状态码们知道了失败的状态码,我们来抛出一个异常,只要我们抛出了异常,由为我们整个下订单的方法,它是一个事物的,所以呢,它就会回滚我们刚创建的所有订单,但我们就使用这种方式来做我们的事物回滚,有没有什么问题来给大家分析一下,我们可以来看一下我们这张图,我们现在呢,订单服务想要下订单,那下订单呢,他前提他要给数据库里边创建订单,这是他要做的事儿,然后呢,他订单创建完了以后,他远程去来锁定库存,一旦库存锁定成功了,那我们就可以来继续做下边的事情,一旦我们这个库存锁定失败了,那以前呢是来抛一个异常,那我们这个订单服务自己来回滚我们的业务。
01:00
但有可能我们这个库存锁定成功以后,我们还要调用其他的远程服务,比如我们下订单的时候呢,使用了哪些哪些积分,我们做了一些优惠,能把这个积分呢,就要在用户服务给他扣减了,那现在呢,我们整个下订单的业务逻辑就是这样,我们一个下单,我们可能会调用几个远程服务,我们这儿有一个下单好在下单呢,然后它重要的在这儿,我们操作数据库,要保证我们的事务特性,那就在这儿金额对比成功,我重要的呢,在这儿有一个保存订单图度,好我们来写一个图度,这个呢比较亮,我们保存订单,然后呢,还有远程锁库存,那如果库存锁定成功,我们想要返回,假设呢,我们再来加上一个业务,我们就不在这儿写代码啊,我们就来写一个东西,我们就叫。远程远程扣减积分,扣减积分,因为如果我们使用了这个积分优惠,我们就可以来远程扣减积分,但我们现在用的呢,全部是我们这个异常机制,我们远程服务出异常来保证我们这一块的回滚,那么说这个有没有问题,那现在呢,来模拟一下,假设我们这个订单服务出异常,也就是我们这个订单服务在创建订单的时候出了异常,那我们的锁库存会不会回滚,首先来考虑我们这儿只要出异常,异常直接代码从此处相当于就崩了,那崩了以后呢,代码都不往下走,我们两个远程服务都不调用,那就不存在回不回滚,因为它都没调用,所以呢,我们现在如果订单业务出异常,那一切正常,OK,订单自己回滚,然后接下来如果我们这个库存业务出异常来看假设呢,我们现在来创建订单,如果我们这个库存服务,库存服务呢,解锁库存出了异常,库存服务由于我们是自制的,我们在库存服务里边解。
02:50
做库存的整个方法也是一个事物,他出异常,首先远程的库存服务自己会回滚,然后呢,把这个异常我们感知到以后,我们会交给我们的订单服务,订单远程调用了这个服务以后,他能知道那个服务出了异常,库存锁定失败了,所以呢他也会回滚,他怎么回滚呢?他是通过异常机制,那如果一切正常,那调用我们远程扣减积分,同样如果我们要来做这个事情,我们就应该在这儿判断远程扣减积分的状态,成功还是失败,如果失败了用异常机制,那现在问题就来了,如果我们现在保存订单成功,然后呢,远程锁库存,它呢是一个假失败,什么叫假失败,我们调了远程方法,相当我们调到了库存服务,库存服务呢,其实给我们锁定库存成功了,但是呢,由于可能我们机器慢,故障卡死,服务器等待等各种原因,我们库存锁成功,本地事务提交了以后,一直给他没返回那。
03:50
一直给他没返回呢,我们这远程调用就有一个超时机制,他一判断超时了,相当于我们他以为我们远程没调用成功,这因为这一块超时了,一超时以后它怎么办呢?我们这个远程服务会抛一个异常,这一块远程调用会出现异常,什么read timeout读取超时,那么经常第一次启动项目都会导致我们读取超时。
04:14
那读取超时我们这一块感知到异常了,相当于我们感知到的并不是库存锁定失败的异常,是读取超时的异常,但只要我们感知到异常,我们远程的这一块,我们的订单这块呢,都会回滚,那现在就会出现一个问题,库存所成功了,库存减了,但是订单没创建来,所以呢,其实他还是有问题的,这是我们第一个假设,我们库存服务出现了假异常。那第二个,那假设我我们这个库存服务现在呢,已经锁成功了,我们又做了远程的执行其他代码逻辑,然后呢,这一块出了异常,比如我们这一块出异常,我们来看哪一块回滚呢,出异常那们现在呢就能看到,如果我们这出异常,假设他本身自己能回滚,他出的也不是假异常,那就是扣减真的失败了,但是呢,我们这异常如果我们从这往出抛,那相当于我们订单肯定会回滚,你们整个订单的事物感知到订单会回滚,但是我们注意,我们扣库存呢,它已经扣成功走到下边了,我们还是一个远程扣库存方法,我们这有异常事物能控到远程里边的吗?肯定控不到,因为我们要远程调方法,这个方法才能执行,我们调过了那就调过了,我们想要他减库存,想要他释放扣除的这些库存,我们相当于还得调一下它的这个释放库存方法,所以们现在呢。
05:43
就会出现两种问题,第一种,那这个远程服务本身出现了假问题,只是我们这个网络抖动,各种网络原因,或者我们所成功了,网络直接断了,我们没收到结果我们以为失败了,回滚订单会出现我们数据不一致,订单下了,但是他给回滚了,没有订单,但是我们库存却给扣了,如果这些做了很多次,那么这个库存全扣了,但是并没有扣到哪个订单里,那这就会出问题,这是第一个异常。第二个我们下边如果出了异常,已经成功的远程调用就没办法再回滚了,我们可以来给大家测试一下,比如我们现在呢,这一块我们现在给大家来启动,我们是以前的代码,我们先来看它能不能扣减成功,那么现在的这个库存服务里边,现在呢,我们就来买上两个商品,一号和二号商品,我们来演示它。
06:34
好,我们去我们的这个购物车,我们直接来购物车们专门来下一号二号商品的这个订单,我们现在来去我们这个手机里边走,我们现在来买上一个商品,第一个是华为MATE30,这个6299,它是一个一号商品,我们加一个这个购物车,好,一号商品我们加到购物车以后,我们再来加一个二号商品。我们一号二号呢有库存,二号呢是MATE30PRO,我们的这个星河营好,我们再加入购物车,我们去购物车结算,我们现在呢不要iPhone了,我们现在就要我们的这个一号和二号商品,那我们现在呢,如果是一切正常状态,好,我们把这个库存呢都变为一件,现在呢,我们现在都要用一件买一件,我们去结算,那如果我们现在去来进行结算,因为这两个东西呢都有货,来看我们的库存这一块,确实一号二号商品,一号二号商品在我们这个二号仓库呢,都有货,而且货物呢充足,如果我们此次下单,那这个这个是成功的,那么现在来看我们的订单表里边有没有数据,好订单表里边没有一个订单,然后我们库存里边也没有任何锁定的库存来下一个单,来看这次下单会是什么效果,我点一个提交订单,好,发现呢,订单提交成功,一切正常,那我们这一块呢,就会有锁定的,每个人锁定一个,而且呢,我们这个订单成功,这是成功的,但如果我们来模拟这个异常。
07:58
首先我们这个远程库存所成功了,但是我们在下边出异常了,比如int I等于十除零,看他能不能回滚,我们就模拟我们的扣减积分出异常了,我们现在来重启我们的这个代码。
08:12
来重启我们的订单服务的代码。也就是说我们已经执行成功的远程服务,肯定呢不会回滚,但这个订单会回滚,因为我们这儿只要一出异常,我们整个订单的这个事务,他操作的自己的数据库没问题,远程服务操作的是远程的数据库,跟自己都没有一点关系。我们order服务也连不了远程的数据库。所以呢,他肯定不能回滚来给大家演示一下这个效果好,我们现在来看我们这个服务的启动状况,我们让等服务启动稳定,我们现在来重新结算一下。那现在呢,就来到购物车里边,我们先来直接调用它的to出的结算方法,这个服务呢,还没有启动稳定,我们稍等一下,我们来进行刷新,好,那们现在来重新结算,现在我们结算这两个商品呢,有货,大家现在注意,我们订单里边呢,只有一个订单,这个订单号结束呢是7954,然后我们这个库存默认呢,现在都只扣了一个,而我们这次来进行下单,因为我们这次下单的话,我们会出异常,我们模拟另外一个服务出异常,我们远程的扣库存已经结束了,而我们的这个订单我们看会不会回滚,哪个会回滚,好我们来点一个提交订单,好,由于我们这个订单出异常,所以他重新来到结算页,二来看我们的数据库,那先来看库存有没有扣减成功,刷新发现呢?库存扣减成功了,来看订单有没有创建出来,我们刷新发现没有创建出订单,原因是什么原因就在这儿,我们已经执行了的远程服务肯定呢不会给你回滚,因为我们。
09:48
所谓的事物就是在同一个连接里边,我们订单服务呢,连接的是订单数据库,所以操作订单在同一个连接里边,远程服务呢,那是人家操作数据库,人家都跟他自己的数据库建立新连接,而且我们都是发的一个新的远程请求,所以跟我们这个服务呢没有任何关系,我们下边出了异常这一块并不能感知到。
10:12
所以呢,我们现在如果我们使用异常机制来做我们的所有的回滚,现在就会出现两个问题,那么说到两个问题,就是我们典型的代表,第一个就是呢,远程服务,远程服务。假失败问题,什么叫假失败?这个假失败就是远程服务成功了,远程服务,远程服务其实成功了,其实成功了就是我们扣库存呢,其实扣成了,但是由于网络故障,然后给我们没返回,我们这个订单服务收到的是网络故障,所以由于网络故障等没有返回,那这样呢,就会导致一个什么结果?导致,导致呢,我们现在这个订单回滚,订单回滚,然后呢,我们这个库存却扣减了,因为我们现在这个库存呢,我们是真的成功了,哎,它是扣减成功,但是呢,由于网络的原因,它导致的失败,这们会出现的第一个问题,第二个问题就是呢,远程服务执行完成程执行完成,执行完成,然后呢,下边的其他方法,其他方法出现问题,出现问题,那这样呢,会导致的现象是什么?就是已执行的远程服务,已执行的已执行,那咱们这个远程请求肯定不能回归,肯定不能回归,因为他们呢,都不在同一个连接里边,所以呢事物控制不住,所以这就出现了我们所说的分布式事物,我们在分布式系统里边,A服务要调B,然后呢,它可能要调CC呢,可能还要调B。只要有任何一个。
11:53
啊,远程服务出现问题,已经成功执行了的远程服务,没办法通过我们的喘塞声道,简单的事物控制机制来进行整体回滚,要回滚,除非他们这三个服务,我们做的不是远程服务,而且呢,操作的都是同一个数据库们,相当于同一个方法的调用,我们只是a service调b service,而不是调远程服务,我们才可以用我们称为本地事物来进行控制,所以呢,我们现在写的这个trans sessional,它呢是一个本地食物,本地事物呢,在分布式系统下,在我们这个分布式系统下,系统下它只能控制住自己,只能控制住自己的回滚,然后呢,他肯定控制不了别的系统的回滚,控制不了。
12:43
其他服务的咱们这个回馈,所以呢,如果我们是数据库修改,我们想要做事物,那么就不能用本地事物,我们就必须用分布式事务,但分布式事务呢,又是一个比较复杂的分布式事务,能产生分布式事务呢,最大原因,最大原因就是网络问题。
13:06
我们这个网络问题,由于我们这个网络抖动,我们无法感知我们远程的这个分布式事物,它是真失败还是假失败,包括我们这个失败了以后,由于我们这个机器拆分,我们是分布式机器,我们的都不操作一个数据库。所以我们没办法控制人家的回滚,那这块呢,我们现在就给大家演示出了这一块问题,那我们这儿只要出问题订单能滚,哎,我们这个订单回滚,但是呢,库存不滚。包括呢,我们说库存服务,如果库存服务是假失败,库存成功的,但是。网络原因超时,超时了然后呢,就会导致还是订单回滚,订单回滚库存不滚。所以呢,现在我们肯定要保证我们下订单的整个操作,订单要都回滚了,那其他所有的操作肯定都得跟着回滚,那么接下来下一节课我们就来看一下我们分布式事务该如何解决。
我来说两句