00:00
接下来我们处理一下秒杀上架的密等性问题,首先呢,我们得考虑第一个问题,就是在我们这个分布式系统里边,我们这个定时任务会出现的这个问题,比如我们这呢,有三台机器,A1A2A3,他们呢都代表我们同一个服务的三个副本,123,然后呢,我们这三台机器,我们现在都有一个定时任务,因为他们都是同一段程序,那定时任务的设置都一样,那等时间一到,我们我们这三个机器呢,假设时间呢都一样,他们相当于就同时启动了我们这个定时任务,那一启动定时任务以后呢,接下来他们就要同时执行我们的上架代码,当然我们这个上架呢,相当于我们只允许上架一次,就算我们这个同时启动,我们只要一个人去来上架就行,所以们先来做的第一件事情,先要在这儿上架,不应该让它有几个服务器就来执行几个这个功能,所以我们可以来加一个分布式锁,也就是说我们为了能锁住我们所有的机器,我们。
01:00
啊,一个人去来执行,所以我们必须做的一件事情,就是呢,我们给这儿来加入一个分布式锁,大家都来启动任务了,没问题,我们呢在这儿先来加一个分布式锁,获取到锁的人才来执行,那获取不到锁的人,如果我们在一段时间内没有执行成功,你获取到了呢,还可以执行,如果我们都已经把这个任务设置完了,那你就可以不用执行了。所以我们现在呢,加一个分布式锁逻辑,那么这一块的逻辑呢,我们先来上来,那现在既然引入了reddi,我们就可以来加一个分布式锁,那先来叫reddi client,先把它注入过来,可能要加的这个分布式锁的这个名字,那现在呢,先来写一下private,由于我们这儿呢要加锁,我就写一个private final string,我来加一个我们的upload lock,我们的上架要用的这个锁,那么现在呢,就叫second kill,那这个秒杀商品,秒杀商品的upload lock。
02:00
那现在秒杀商品的上架功能的这个锁,我们准备了一个这个锁,我们呢,只需要给这儿来加一个分红式锁,得到锁的人再来执行,那没有得到锁的人,等别人释放锁了,你看人家执行成功了,没执行成功你就不用执行了,所以我们在这呢,先来锁住一下upload lock,点一个我们不是它,我们来调用red client,好,我们来获取一个分布式,点一个get get一个lock lock的名字呢,那就是它,你先来获取一个分布式锁,那们得到这个锁以后呢,我们先来给它锁住,锁住以后我们再来执行这个代码,我们点一个lock,那这个锁住以后呢,我们可以指定一个释放时间,比如我们这个十秒,十秒呢,我这一块呢,预计就执行完了,他们units来写一个十秒。那我们这个方法呢,整个执行完了以后,我们再来给它unlock来做一个解锁操作,我们在这呢,应该来使用try finally,我们无论执行成功与否,我们最终呢都要来给它进行解锁,TRY,那就是它,然后呢在这来做一个finally来进行在这解锁,好现在呢,我们相当于使用分布式锁,我们先来锁住我们这些任务,那锁住以后呢,接下来拿到我们这个锁的机器,再来执行我们这个业务代码,它执行完一释放锁,别人再来获取到锁以后,一看呢,我们这个已经上架完成了,他就不用执行了,所以我们现在呢,先来加了一把锁,加完锁以后呢,我们再来处理这个代码里边的密等信,上架完成以后,我们就不用上架了,那么接下来处理这个密等信,第一个保存活动信息点进来,那么这个活动信息呢,我们这个保存是用这个K来进行保存的,所以我们得判断一下,如果这个key呢,已经有了,那么就不用保存了,我们red the temp来。
03:50
调用一个exists,我们来判断一下我们这个东西呢,是不是在red里边存在的,而且呢,它这有一个方法叫count,相当统计我们这个K存在的这个数量,我们来看它还有一个方法叫汉字K,我们来判断red里边有没有我们指定用的这个K,好那就来直接来做一个判断,如果有我们这个KF,如果汉字这个K说有我们这个K的情况下,我们就不做了,没有我们的这个K,我们才需要来做这件事情,那这件事情呢,我们来放到这,当然这个K的整个判断,我们可以先在这儿来做一个执行,好我们在这儿,在这儿呢,我们来拿到我们来判断,有了的话,我们再来获取所有的数据来给你来执行这一块的操作,好这是我们来做的第一个,第二个我们再来保存SKU的信息的时候也一样,那现在呢,来遍利所有的SKU的这个session信息,来每一个商品拿过来。
04:50
我们在这儿准备好这个to数据以后,我们在这options来进行保存,包括我们要保存到每一个数据,我们都应该来做一个测试,特别是我们这个信号量,如果我们来重复做多次,比如现在正在秒杀,由于另外一个机器呢,它的这个定时任务可能反应的比较慢,它现在呢,我们正在秒杀期间,他给启动这个任务了,一启动以后呢,接下来我们这个秒杀本来已经剩了零件了,然后呢,我们重新进来,又给他设置了100件,那又可以秒杀,那这就造成了很大的损失,咱们在这呢,一定要每一个做之前都来做一个判断,如果说原文这个秒杀呢,使用的这一块件,那在red里边存在的就是我们这个信号量呢,其实就是我们一个普通的件,我们就要来看这个键存不存在,所以我们来判断一下,那这个red点一个hands k,如果我们有我们指定的这个K,我把这一块呢,CTRLC复制过来。
05:49
好,我们把这个呢得到一下,我们来判断,如果我们没有它的情况下,它呢返回一个true false,那如果是true,那就是有有我们就不执行了,如果是false我们就来执行,非false,那这个就是处,那就给它执行设置信号量啊,这是一个第二个我们还要给它里边保存这些数据,那这个设置信号量呢,我们可以来放在最后边,跟别人呢又没啥关系,那保存这个数据的这一块我们也一样,如果我们都已经有了这个key options,我们来统计一下,我们在这呢,有一个options,点一个汉字key,我们已经有了SQ,当前的这个商品信息,我们就不用给里边put了,好,我把这一块呢拿过来CTRLC,那直接来放到这,那这个我们来判断一下,If,要说当前我们每一个保存的这个SQ缓存的这一块,那就是这个,如果我们都已经有了。
06:50
这个商品的信息了,那也就不用put了,所以我们在这儿再来判断一下if,它不存在不存在呢,我们缓存里边的商品,我们才要给red里边来进行保存,那这一块的操作,那再来进行一个执行,所以呢,这就是我们来保证密等性的操作,当然我们这一块呢,要生成一个随机码,这个随机码呢,两处都要用,把这个随机码的生成放到我们这个一遍利进来,我们就来生成一个随机码。
07:18
然后呢,我们来判断,有的情况下那就没必要做了,没有的情况下呢,我们才有必要放进去,这是我们来写的密等性保证功能,我们来看一下这块呢,还有一个错误来点过来,我们这儿呢,少了一个小括号走好,那么这块代码呢,整个写完以后来做一个测试,我们看现在能不能保证密,那现在还是把red里边这个秒杀相关的这个数据呢们全部清空,那现在让任务呢,我们来多启动上几遍,好,那现在来直接执行来启动我们的这个项目,走们让他在这儿来进行判断,那如果我们这个已经上架了,就不应该上架,所以我们这个每分钟在这儿执行的话,那我们这个效果为了更明显,期间把这个定时任务呢,来再放小一点,我们让它每隔三秒就来执行一次新杠三不长呢,写一个三,每三秒我们就来执行一个上架功能,那看能不能重复上架一些商品信息。好,我们先。
08:18
那这个项目呢,启动起来,我们来等待它这个上架我们这个商品信息,好上架商品信息这是第一个,然后呢又上架,我们来看会不会重复来刷新一下,来确认一下我们上架的好两个场次,那我们现在呢,每一个商品它都不会给后边多添了,好然后呢,再接下来SKU的信息,只要有了,他也不会多添了,没问题,还有我们这个库存信息,那么这个库存信息呢,我们来看一下,那现在呢,关键就是这个问题,那这个库存呢,只要我们每上架一次,由于我们这块会生成一个UUID,所以呢,我们这儿只要一重复执行,我们这呢,都会为这个UUID来生成一个库存,那么把这一块呢来处理一下,那来到这儿我们还是把这个任务来停了,主要就是来到我们这个库存这一块,好,那这个库存的整个SQ这一块的信息,那在这呢来判断,如果这个SQ商品呢,信息已经上架了,我们就不需要上架了,同样的那上架这个商品的信息,那与此同时呢,我们也会。
09:18
给他上架我们的这个库存信息,这两个是一体的,所以我们这一块库存的这个判断,那倒没必要把这一块呢拿过来,只要我们这个商品跟它的整个库存同时上架了,那么下一次呢,进来就不用上架这么多了,那还是把red这一块的来重新清空来删除。那么要删除的呢,不只是这里边的数据,我们整个那这块呢,全部商品。全部删除好,我们现在来重新来刷新一下,来保证我们这次呢,不会有那么多的库存生成,因为每一个商品呢,都会与它唯一的一个信号量的生成,好来重新来启动来做一个测试,好那现在来看一下我们控制台,那我们这个服务呢,现在来启动成功,来开始上架我们的商品,好这个上架呢,已经打印了又一个上架打印了多次,我们来刷新一下,看一下。
10:10
在这个里边两个信息,那第一个第二个没问题,然后呢,包括我们这个也没问题,因为我们呢,现在有一个二号商品,我们现在要上架,我们这个二号商品呢,要上架,然后二号商品的这个库存,这个库存呢,发现现在只有一个,其实这个问题就大了,因为我们呢,巧了,正好是我们要上架的这两个场次,我们都有这个二号商品,所以我们在这儿要判断的这个情况,应该是我们这个场次的这个商品,如果呢,它的这个信号量设置了,我们就不用设置了,否则呢,我们就需要设置好,我们把这一块呢停掉,我们把这个逻辑呢,改成下边的这个信号量在这儿,那如果当前这个当前这个场次的商品。的这个库存信息,库存信息。
11:04
已经。上架就不需要上架。所以我们把这个信号量的单独上架判断我们也得拿出来,那每一个商品呢,上架完商品数据以后,还有它的这个信号量信息我们也上架了,而且呢,大家注意这块呢,还有一个问题,比如我们看我们SK要秒杀的这个商品,二号商品,二号商品呢,其实我们现在有两个场次都有这个二号商品,他们的开始结束时间都不一样,而我们这一块呢,只有一个现在保留了最后一次的内容,所我们这一块和这一块的内容现在都出现了问题,那么就应该是每一个场次的这个信息,它的这个保存呢,我们在这儿来重新处理一下这一块的VALUE6,我们就不保存成我们当前的SQID了,我们最好保存成场次到我们的这个SQID,那这样我们后来呢,也在后边好处理下一块这一块来保存的时候,这就是第一场我们这个12点厂的二号商品,它的这个信息是什么,所以我们现在呢,重新来保存一下,来到我们的这一块。
12:12
主要来保存,我们先来我们这个场次里边,保存它的这一块,来到场次里边,场次里边呢,要收集我们这个ID,那这个ID呢,就是两个ID的加集合,我们现在点一个get ID,这ID是场次ID,我们场次的活动ID,那就是它这个ID我们来再加,再来加上我们的SQID,那就这一个活动场次。然后呢,他的这个商品我们来给他进行一个上架,所以我们来在这儿这个场次的这个商品信息我们就来保存了一下,那同样的我们这个场次呢,既然上边这一块变成一杠二了,那为了在下边来找商品方便,那这个里边现在包含了一杠二商品,二杠三商品么?我们在这一块来保存商品信息的时候,也应该存成我们这个一杠222杠三来到这一块来看一下,我们来保存的时候,Put,我们现在呢。
13:07
保存的是每一个商品的这个ID,我们现在呢,还得加上场次的ID来get promotion这个ID来to丝转一下,我们来把这两个呢来拼接一下,我们都是来使用下划线。我们来看一下我们这个上边,上边我们这一块的这个拼接也是使用下划线,那这一块呢,一拼接以后,那么这块呢,每一个场次的SQ信息,我们在这呢,也就保存起来了,只要他当前场次的这个信息已经处理了,我们就不处理了,所以我们在这来要做的判断,那判断呢,就是当前场次不只是SQID了,是当前场次。的这个string来加上我们这个下划线,也就说我们一拼接上来,我们按照它来作为我们的这个判断,如果来他有的话,我们就不用放了,如果没有的话,我们就在这放,而且呢,每一个场次放好以后,还有它的这个库存信号量,那么这块设置完了以后来重新启动,我把red这一块呢来清空一下,重新删除,所以这一块的设计呢,一定要合理,而且呢也要方便我们来查询操作,来看一下我们现在的整个效果,来同时来修改一下秒杀流程,那这一块我们来保存的就不是SQ ids了,现在呢是session ID杠,我们的SQID每一个呢都是这样。
14:34
我们来当前场次里边,我们来相当于当然场次有哪个商品,当然场次有哪个商品,我们都在这儿呢,有一个保存信息,而且我们按照这个信息,我们去这也保存。去这查询也方便,我们现在呢不查SQID作为K了,那现在呢是来作为一个我们的这个session ID,那现在相当于来加了一个session ID这个环节,所以SQID来找一下,那现在来给它加上session ID-SQID,那这个呢是来作为K的,好我们把这一块重新来写好了以后,我们来看一下我们控制台这个上架呢,已经上架了好多东西了,然后我们来重新来看一下们red里边的数据,走保证我们这个数据里边呢是有的,那二号我们这两个场次呢,有一个五杠二和四杠二这两个商品,然后呢,五杠二商品的信息是这样,四杠二商品的信息呢是这样,然后呢,我们库存里边每一个商品呢,都有它的这个信号,量好没问题。
15:33
那么这个商品的整个上架功能密等性处理我们也结束了,而且呢,就算我们这个定时任务同时启动,由于我们要获取锁,所以呢,获取到锁的人先会执行,然后他一释放锁以后,下边的人才会执行,那么才会引发这一块的判断,有的同学说,那既然我们这一块都设计成密等了,我们不加锁行不行,这个肯定是不行,如果不加锁大家同时进来,如果同时进来呢,同时在这假设都走到这一行,判断呢,我们这个red里边没有,然后呢,大家又同时相当于给两个里边同时放了,而假设它放的快,它放的慢,那下一个呢,相当又是给它一个一个追加,所以呢,整个过程我们得一定先有锁,有锁的人做完了以后才能保持他的状态释放锁,那下一个人再去做,你看别人做过了,那就不做了,所以我们这个锁也是非常重要的,只有我们这个所执行完成,执行完成所。
16:29
的业务,咱们这个执行完成状态已经状态已经更新完成,更新完成,那这个接下来释放锁以后,释放锁以后,其他人获取到才能得到我们这个。整个原子性的状态,其他人过去到就会拿到,拿到最咱们这个新的状态,最新的咱们这个状态,那么这个业务状态呢,相当于它就是保证了整个原子性,不可能我在执行期间,别人还能获取到我一个中间状态。
17:01
好,我们把这一块呢,就处理成功了。
我来说两句