00:01
各位同学大家好,刚才呢给大家讲到了分布式锁,我们在read里边通过set NX进行上锁,通过disappear来设置过期时间,包括咱们在里边可以释放锁用DL来实现,而在过程中咱们可以把这个上锁和过期时间同时进行,这里边实现一个原子操作,这样的话能保证这里边当我上锁之后出现异常产生的问题,所以这是我们刚才给大家演示的。然后咱们下面的把我刚才说这个过程呢,咱们通过编写Java代码给各位也来做个演示,演示之后咱来讲解分布式所中的其他的问题,那咱们来写个代码,这代码应该并不复杂,我们来看一下啊,之前呢,咱从用这个损boot整合过我们的red,不是各位是否记得啊,我们引入依赖,然后在里边我们加入配置文件,再写上write这个配置类,然后在CTRL里边通过red to来做这个操作。
01:09
那下面呢,在里边有单代码,这个代码我给各位就直接复制过来了,然后咱们详细看一下这个代码到底是什么含义,我们来看一下哈,应该很简单,首先我们一个方法,用盖子提交,它里边的第一步操作就是设置锁,或者说上锁,这里边怎么做呢?大家看里边的这个代码啊,类似于咱之前在我们那个就是red中用那个set NX做操作,那比如说咱的名字叫lo,直是幺幺,好比说咱们用SNX就是这个命令。里边是lock,然后111用它进行操作,这个设置如果成功,反而是个布尔类型,就是true和false,然后下面咱们判断,就这句话,如果说它返回处表示我们上锁成功,就是锁已经给它加进去了,这值是处,如果加锁成功怎么做呢?我们从write中来取个值,就这个number number呢在里边,比如说给它先做个设置set number咱们等于零,咱就把这值给它获取到,然后获取之后我们判断值是不是等于空,如果值不等于空,把这值怎么样给它就加一,加一之后这项代码,那咱就是释放错,然后里边就来做这操作,但是这个锁如果说你没有获取到,那我们等一会儿重试,重新再进行获取,这是我们写的代码,过程怎么样呢?其实很简单,就是第一步,我们操作中先上锁,然后咱们得到这个number值,把它的值加一,加一之后我们再。
02:47
释放锁,如果说这个锁咱没有得到,表示没有上锁,那我们等一会儿再继续进行获取,所以里边就是这么一段代码,通过write to这句话是上锁,这是取值,然后这是释放锁。
03:03
里边就是完成了这么一个操作,那这个我们就做到了啊,然后做到之后呢,下面咱们把代码做个测试,这个测试呢,其实我们直接访问就可以了,但是为了我们更加明显,咱们还是用一下之前给大家讲这个AB测试的方式,用它咱们把这个代码来测试一下,那我们来试一下啊,比如说我们看一下现在在这里边。应该只有我这个number number的值目前是零,然后咱们每次往里边加一,然后来到这个终端中,在里边用AB测试,我们来试一下,我里边有这么一个结构,咱们把它来改一下啊,改成我们当前这个IP,包括路径,那我们来改一下啊。首先我们看啊,我当前IP应该不是这个IP,那我来找一下啊,找一下我这ipp conig当前我的IP应该是这个2.80,所以咱位改成我这个2.80这位置啊,改一下。
04:08
二点。808080端口,然后后面呢,加上我这个路径,我这路径叫test,把这个给各位拿过来啊就是。太子道。然后在后面加上角test lock,咱们检查一下啊,B写错应该是它,所以现在这个我们路径就写对了,写完之后咱通过AB测试来试一下最终效果,如果正确的话,每次加一,就是每次先上锁加一释放锁,上锁加一释放锁依次进行,应该有这么多次操作,就是有1000个请求,100个式并发,那现在咱把它执行一下,我们来看一下就是这效果啊,看它是怎么样的。大家看啊,这里边应该执行这个1000个请求,最终完成了,完成之后我们到里边再来get一下A,大家看它的值是不是1000呀,证明咱的代码就是正确的啊,就是咱们通过代码把刚才效果做了一个模拟,这是我们做到的啊,但是这个代码咱刚才说到有个问题,比如现在我上锁之后,突然出现了问题,中间有异常了,那这里边咱就不能释放锁,所以说咱可以设置一下这个锁是不是有一个过期时间,要把它给做设置,那怎么设置,咱们在我们的ready中通过去撇,或者通过set n X ex设置,而代码中跟它类似,就是我们在这个方法里边,大家看啊,就是这个位置。
05:46
加上你的时间就可以了,那现在给各位来设置一下啊,我们来到这里边,比如说我加上一个时间单位,再来一个三,后面加上一个叫这个time union,然后加上一个叫second,大家看这结构啊,这是时间的值,这是时间单位,这么做就表示咱设置这个T,三秒以内,就是三秒之后它会过期,所以里边用这个来操作啊,这是我们如何设置搏及时间,这个我就不用测试了,各位可以自己测试一下,效果肯定是没有问题的,跟我们刚才是一样的。
06:25
所以现在把这个给各位做一个说明,咱们把刚才用ready做的效果通过代码做了一个演示,各位再次感受一下这个过程啊,然后这个做到之后呢,咱们继续往下说啊,就是咱们目前这个上所释放所分布式式所过程中其实还是存在问题的。那大家可以想一下啊,目前操作中,你说我们还存在什么问题呢。大家可以想一下还有什么问题。给各位啊,重复一下啊,然有什么问题,那就是锁的这个木山或者锁给他释放错的问题,比如现在我释放本来是我的锁,我没有释放,我释放了别人的锁,然后别人把我的锁又释放了,那这问题是怎么产生的呢?给各位我来说一下啊,咱们在图上来画一下,比如说我现在啊有这条数据,然后现在我有三个操作要操作这个数据,比如说三个操作分别是ABC啊,比如这个是A。
07:27
这个是B。然后这个是C,咱们有三个操作要操作这个数据,因为咱是并发嘛,假如我现在啊,这里边我们约定每个操作里边的key就是那个锁,它在就是十秒内啊,这里边就是是一个过期时间,我们做了一个设置,那比如现在怎么做呢?比如现在啊,我这里边就是A操作先进行的那A操作,比如说他在进行过程中啊,就A操作它进行过程中,首先第一步A就是先进行操作,我写一下啊,先操作他操锁中的第一步是不是先上锁,要然后上锁之后第二步做那个。
08:08
具体操作这个我应该明确啊,就是A现在他先抢到了,他先操作,那他的第一步肯定是先上锁,然后第二步做具体操作,比如说啊,他在做具体操作的时候呢,他这个台服务器突然是一个卡顿的状态,就突然卡住了,一直没有动,而一直没有动呢,也超过了十秒,那这个时候大家说一下会有什么问题,我现在操作上锁,然后操作操作的时候服务器突然卡住了,它不动了,这时候超过了十秒,那这个时候我这里边这个锁是不是就会自动释放了,因为你超过十秒,如果你这里边。这里边它的key就会自动释放,咱们设置了过期时间,就是现在他做这个操作,比如说啊,我A操作释放锁之后,大家问各位A的操作结束了吗?大家想一下他结束了吗?没结束吧,他只是卡住了,后面是不是还要继续操作呀,比如咱先放到这里,他操作并没有结束,假如说他一释放,那B和C是不是要抢这把锁呀,假如现在啊B他抢到这把锁啊B。
09:16
抢到了这个操作,那他抢到之后呢,首先还是肯定是先上锁,然后做操作,就是他把这锁抢到了啊抢到这把锁,他上锁,然后他做他那个具体操作,我写一下啊,第一步B抢到锁,第二步做具体操作,假如说现在啊,这里边在做它B正好在做具体操作的时候,假如他刚做了一秒的时候,这时候A这服务器啊反应过来了,A是不是巨型操作呀?啊就这个时候A这台服务器它反应过来了。比如他有了反应,然后反应过来之后呢,他肯定会继续操作,而他操作之后,最终他是不是要手动去释放锁呀,因为它里面设置这个规则,最终都要释放锁,如果你能自动释放自动不能自动,每次我都要手动,但是你注意啊,因为A的锁是不是已经自动释放了,而他这个手又要手动释放,那大家说它会释放谁的,或者说目前锁在哪里,是不是在B的这个位置,所以它这释放中就会把这个B的这个锁释放了,这个锁。
10:26
就是B的这个锁会被释放,因为B现在只做了一秒操作,他没有做完,但是这个锁被释放的,而释放不是自己释放的,是由A给它释放的,所以大家发现啊,这个问题肯定是不对的吧,我B的锁怎么可能要被你A释放的,是不是要是我自己释放呀,而我A你要释放,你肯定不能去释放别人的锁,必须只能释放自己的锁,所以目前就会有这个问题,就是我的A释放别人的所,而我这个锁被别人释放了,这是我们在这个分布式锁中会产生问题,就是你释放过程中可能释放错了,没有释放自己的,而把别人的锁给它释放掉了,这是咱们说明一个问题,大家把这个好去看一看啊,这是咱们遇到问题。
11:17
那问题遇到了,咱就要想它的解决方案,那大家考虑一下啊,这问题咱们该怎么解决呢?怎么解决,A只能释放自己的,B只能释放自己的A,不能释放B的锁,那各位说这怎么做?给各位说一下啊,肯定是有多种方案,而有一种最典型方案给大家说一下,咱看里边的这句话。使用这个UUID防止误删,就是只能删自己的,而不能删别的,那什么意思呢?也就是说我们现在啊,在操作中,当你在上锁的时候,咱的语句是不是用这个set我写一下啊,就是set加上你这个K,然后加上你的值,但这值呢,之前咱是随便写的,目前不能随便写,咱们为每个操作都生成一个唯一的随意一个值,我们叫UID啊,比如说A的C值叫幺零,10111 B的值跟它肯定不一样,C的值跟它也不一样,每台服务器有自己V的个值,然后后面加上NXEX,加上它那个默认的过期时间。
12:25
所以咱们通过这个UID来做设置,设置它里面这个V值,然后用它做判断,大家注意这是我们的第一步,而这步做到之后,我再写一下啊,就是第一步。我们通过一个UUID来标识一下你不同的那个服务啊,就是表示。我们这里边不同的那个就是操作,比如说我这里边第一个机器有自己的UID,第二有自己的,第三个有自己的,每个肯定都不一样,而里边就是第二步操作,当我们在做这个释放锁的时候,咱们首先呢做个操作,先判断一下你当前的UUID和你那个要释放所里边的UID是否一样。
13:16
这个应该各位好理解了啊,如果一样的话,咱是不是释放,如果不一样咱是不是就不释放,所以通过UUID来做这么一个判断,这就是我们最终的解决方案,咱用它来解决这个就是误删的这个问题,自己只能删自己的,不能删别人的,我的锁只能被我放,别人也不能释放我的锁,这是我们说的关于这个问题,那问题怎么解决呢?给各位来改造一下啊,其实很简单。我们操作中呢,首先第一步咱们先生成一个UID多种方案啊,咱就直接用Java中最基础这种方案,比如说我们来一个UID,等于这个UUID点上random u ID点这个to string。
14:03
用它设成一个值,然后咱们每次上锁的时候呢,把这值都换成UID,因为每个次的值都不一样,让每台服务器都不相同,所以里边做这个操作,而我们最终在释放锁的时候,大家看这里边是释放锁呀,在释放锁的时候呢,咱们做个判断,比较UUID值是否一样,如果一样的话我们释放,如果不一样,那咱们就不进式法,那咱们给它做一个最基本的比较,我们写一下啊,首先我们通过redto.opsfory6.get,这个名字叫lock,就是咱们设置这个值。然后lock呢,返回咱们那个UID啊,比如说我们叫这个string,咱们给它做一个转换啊,这个值我就叫lo u u ID。这里边咱给它变成这个string,然后变成之后下面咱做个比较,就是我现在在我那个ready中,这个就是UID值和我当前的UID值,如果说它们一样,那咱们再进行锁的释放,如果说他们不一样,那我们就不进行释放,所以通过一个UID来解决这个就是锁误释放或者误删的问题,让自己只能释放自己的锁,所以这是一种解决方案,各位把这个给他要知道。
15:36
所以现在我们就把这个问题给大家又做了一个说明,关于这个就是锁误删的问题,通过UID来解决这个问题,我们是通过Java代码把这个问题给各位又演示了一遍,所以各位把这问题一定要特别的清楚。
我来说两句