00:00
前面呢,我们测试了一下,使用C卡来控制我们的分布式事务,发现呢它是可以控得住的,那我们西塔的这个分布式事务默认呢,使用的是它的这个at模式,那在C塔这一块了解的时候,他说支持了好多模式,现在呢使用的是at,这at呢,其实还是基于我们之前说的二阶提交的一个演变,只不过我们的这个二阶提交跟我们说的这个二阶提交稍微不同的是,以前的这个二阶提交的第一阶段是一个准备阶段,只是一些准备数据,他没有提交数据,而西塔的第一阶段他是直接把我们本地事务就提交了,但是呢,接下来来到第二阶段,我们想要回滚的时候,他是通过回滚日志来做的一个反向补偿,相当于我们数据库里边,之前事起他又给改回来,这是我们C他来做的分布式事务,当然除了这些at模式,还有我们自己来编写,T c try con和cancel这些代码呢,我们都可以来自己编写。当这些。
01:00
Apcc模式的代码大家都可以参照西塔的这个事例,我们在西塔快速开始,他说这一块呢,有这些事例点开在这一块的西塔samples里边。我们看到下边呢,有非常多的示例代码,比如我们想要TCC,我们就可以进去来看它是怎么做的,我们想尝试这个cga,我们就可以进去看它是怎么做的,这一块呢,大家都可以来参照相关的事例代码,每一个事例代码里边呢,也都有详细的说明,好这我们说的这个西塔分布式事务,但是呢,我们说我们这个分布式事务,如果下订单,我们使用C塔的这个2PC模式,就是C塔的自动提交at模式,这样呢会带来很大的问题,就我们这个模式呢,它适用的场景不是高并发场景,它适用我们一般的分布式事务控制,我们这个C塔的at模式最适合在哪一块应用,比如我们之前写过一个商品服务,来打开来看一下,商品服务里边呢,我们之前写过这么一处代码,来找一个叫SKU的保存s puu英仿好,我们在这保存SPU的时候,那们传入了s puu的VO,这是我们后台管理系统将s puu的所有数据收集起来以后。
02:12
然后呢,我们调用这个大保存方法,而pou的这个大保存它呢,除了给我们本地的一些表里边保存数据外,我们看到呢,它还会远程调用,我们一直往下,诶发现这一块呢有一个cup份,那么这一块呢,有一个远程调用保存优惠券信息,包括呢上边肯定也有远程调用,那么这呢,还有一个是来保存我们积分信息,所以我们发现呢,我们会发生几次远程调用,而这个远程调用呢,我们肯定要么都成功,要么都失败,所以我们来保存商品信息的时候,这一块我们最适合使用C塔的分布式事务,来使用我们的这个global transition,所以呢,我们说这个场景呢,我们的后台管理服务来提交一些增删改查数据,它不要求超高的并发,然后呢,我们提交成功了就成功了,失败就失败了,那在这一块呢,适合来做C塔的at模式,使用我们这个C塔at的这个分布式事务。
03:12
那除了这些后台管理系统的这些简单场景外,那如果是我们的一些高并发场景,比如我们这个下单这个呢,就不适合了,我们这个下单的典型就是高并发场景,我们后来呢,可能会有大量的流量同时进来,那我们如果使用西塔这种来控制事物。大家可以大致的来看一下我们西塔在at这一块怎么做的,首先呢,它有几大步要获取全局锁的,还有各种锁的,我们这要隔离都是要使用各种锁机制的,所以呢,一做一个事物,我们发现呢,它会加超多的锁,一加锁以后相当于把并发变成了一个串行花了,所以呢,我们整个高并发起来,如果我们订单都这么来做,所有人呢,都可能得等待上一个订单下完再来下下一个订单,那这样呢,我们整个系统就没法用了,所以在我们这个高并发里边,我们肯定解决分布式事务,不去来考虑我们的RPC模式,包括高并发里边呢们这个TC这个事物补偿方案呢,我们也不去考虑太多,那么最终在高并发里边呢,我们希望能考虑的是以下的两种方案,以下的两种呢,都是基于我们这个消息服务的,也就是说我们可以来通知你,我这个事儿呢干完了,然后接下来你收到通知以后呢,后边。
04:31
再来干,所以我们现在库存的这一块,我们最终呢,推荐我们在库存这一块想要回滚的话呢,我们不使用我们这个西塔的分布式事务,那我们使用什么呢?我最终来使用这个叫可靠消息加最终一致性,大家看着这一块呢,叫最终一致性,什么叫最终一致,那以前呢,我们可能会导致我们这个订单的下这一块呢,成功了,锁库存呢,我们锁失败了,或者库存是锁成功了,但是在下边出异常了,导致订单滚,库存不滚,那我们为了让库存滚使用了西塔,但是这种呢,效率极低,我们可以这么来做,那为了能保证高并发,为了保证高并发,为了保保证高并发,我们怎么做呢?我们下订单这一块,订单自己该滚还是滚,但是我们现在存在的问题就是,一旦我们订单回滚了,我们这个库存服务呢,也得自己回滚,所以我们这个库存服务库存服务库存。
05:32
服务我们这个自己回滚,那么这个库存服务自己回滚,怎么回滚呢?我们可以在订单这一块,比如我们这个订单业务做完,我们在submit order这一块呢,我们做完了以后,我们controller把它调完,我们知道呢,它出现异常给回滚了,我们可以发一个消息告诉我们的库存服务,说这个订单都回滚了,你把刚才整的那个库存自己去解锁,所以我们呢,不需要来调用我们的回滚代码,我们只需要发一个消息,所以我们的性能损失是几乎没有的,就是我们这块呢失败了,我们呢可以可以发消息给我们这个,可以发咱们这个消息给我们这个库存服务,这是我们说的第一种,当然第二种,那库存服务呢,我们本身也可以自解锁,库存服务本身我们也可以呢,使用自动解锁模式,自动解锁模式。
06:26
这样呢,我们下订单连消息都不用发了。无论是成了败了,我们库存呢都会自动解锁,那怎么自动解锁呢?我们最终都是要参与消息队列,我们要使用消息队列来完成这个事情,那怎么使用消息队列完成这个事情,大家可以来参照我们这一块消息队列的流程,那将来呢,我们消息队列会涉及的比较复杂,主要我们来看库存解锁这一块,我们的理想设计呢,是如果我们哪些库存想要解锁,那呢,你需要给我发一个消息告诉我,然后呢,我们专门的库存解锁服务去来订阅我们这个队列里边的消息,那你给我发消息的时候,比如用路由件to release,我知道是要库存解锁,然后呢,你消息发给我们的这个交换机,交换机呢把这个消息路由给我们这个队列,然后呢,这个队列里边存的这些消息都是库存要解锁的消息,然后呢,我们这个服务只要收到了,那他就在后台慢慢的去来解锁消息,我们呢,不用保证强一致,我们哪怕是20。
07:29
分钟,30分钟乃至于一天以后把这个库存解锁了,最终一致了就行,所以呢,我们可以来使用消息队列来完成我们的这个最终一致性,那这一块的完整逻辑怎么用?我们呢?说我们现在设计的呢,会加一个东西叫延迟队列,这块延迟队列呢,我们后来再说我们主要逻辑呢,我们来给大家看一下现在我们的这个所库存服务,我来看一下增强版逻辑,增强版逻辑我们想要所库存的话,我们先来保存一个库存工作单和库存工作单详情,来修改一下我们的库存服务,我们现在不用C塔来控制事物了,来到我们的库存服务来找一下我们的V,我们呢会有一个v service,我们直接来CTRLN,我们来打开我们的库存服务,V service的实现主要是v SQ service的实现,好我们在这一块呢,有我们的这个解锁,这是我们来锁定库存的这个方法,那我们希望的就是我们在这儿锁定库存的时候,你没锁了一个什么库存,你。
08:29
你呢,给我数据库里边先来记录一下,比如数据库里边专门有两张表是库存工作单,这个工作单呢,表示我们这个订单现在想要锁库存,那锁成什么样,在详情里边,每一个商品锁几件,包括呢在哪个仓库锁的,我们也可以给他加上这两个字段,那我们后来写的时候呢再加,所以相当于只要我们想要锁库存,我们呢,先给数据库里边保存记录,我要锁库存,接下来呢,我们就来进行锁,只要锁成功了,那一切OK,如果锁失败了,数据库里边呢,相当于没有这个锁库存记录,因为锁失败呢,我们这个本身自己锁失败会全部回滚。
09:09
但如果可能是这种失败,比如我们来到订单里边,我们库存呢,其实自己锁成功了,在这儿呢锁成功了,但是呢,我们订单下边的其他完了,然后库存呢要进行解锁,那怎么办呢?我们相当于数据库里边,就我们当时所库存的记录,我们呢可以使用一个定时任务,比如我们假设有一个定时任务,我们每隔十分钟扫描一下数据库,看我们数据库里边的这些订单,哪些订单呢已经被取消了,或者这些订单呢已经被回滚了,然后他的所库存消息还在这儿存着,我们就把这些消息呢拿出来,把库存呢重新解锁一下,当来做这个定时任务,定期来扫描全库是一个很麻烦的事情,所以我们来引入一个东西叫延迟队列,那么所库存的整个完整流程呢,我们后来再说,大概呢,我们现在会用到一个延迟队列,这延迟队列呢,是来做一个定时功能,比如我们这个库存锁成功了,我们害怕订单失败了,我们库存呢要自己结算。
10:09
做,那么呢,可以把所成功的消息我们先发给消息队列,但是让消息队列呢,先别往出发,先别让别人收到,让他在这儿呢暂存一会儿,比如我们来存上30分钟,因为我们现在呢,订单有可能我们是成功了,也有可能是失败了,无论是成功失败,那30分钟以后呢,订单不支付,我们都给它关了,所以30分钟以后订单肯定就见分晓了,它是成的还是败的,如果30分钟以后,我们把这个消息呢,再发给解锁库存服务,解锁库存服务呢,一看这个订单早都没有了,或者订单都没有支付,被人取消了,所以我们就可以把当时所的这个库存自动的解锁一下,相当于我们这儿呢,整了一个定时的我们库存的解锁消息,咱们订单几十分钟失效以后,它呢才开始进行解锁,我们想要完成这个功能,就要使用到我们的延迟队列,那库存的整个自动解锁功能,我们来讲完延迟队列的时候呢,我们再来详细说,那接下来我就来说一下延迟队列。
11:09
嗯。
我来说两句