00:00
那有同学呢,问了我这样的一个问题,说老师咱这个位置都不使用DV调用了。那还要不要去睡眠了呢?之前为了防止地位调用出现占内存溢出,我们这里呢,使用了睡眠时间。那么现在呢?我都不使用DV调用了,那还要它有什么意义呢?他有意义啊。它呢,可以使我们的竞争变得更加小了啊,竞争压力变得更小了。我们这个本质啊,是使用的是CS来实现的,你可以认为啊不停的自旋,那么来去实现,那就获取锁。如果你把这个睡眠时间给它去掉了,就会导致我们所的竞争压力变得更大了。那从而呢,使得我们的性能就会降低。虽然这个睡眠时间咱不用去掉,你就放在这里就可以了,我们这个锁实现之后呢,我们来去分析一下,咱们这个锁呢,还可能会存在什么样的问题。那么,既然聊到锁,我们不得不去聊思索问题。
01:03
所以然,第二个特征,我们要聊的就是防死锁的发生。防止防死锁发生啊,哎,那么我要防死锁发生,那你得要分析一下什么情况可能会导致死锁。那你分析出来情况之后吧,我才能避免才能去解决啊。好,那假如说呢,我这里呢,有两个氟,一个是一氟,一个是二氟,我这里确实有这两个氟。那我将来可能还有三服务,四服务呢,有很多服务呢,搭建了一个集群。那么假如说一个请求通过一这台服务器,然后成功了,获取的成功了这个成功的获取的这个锁。成功的获取到锁了。那会到锁之后呢,可能还没来得及执行业务逻辑呢,比如在这个位置呢,服务器,服务器宕机了啊服务器宕机了。那么一旦等级了,那么我们这个释放所这个位置还有机会执行吗?
02:04
就没有机会执行了。那没有机会执行,那么咱的锁这个lock,锁lock这个key一直就会占用着啊。那么即使234服务器是健康的。那么由于获取不到lock锁。那么他们呢?也只能被阻塞着。即使一呢后续启动起来了,那这个锁呢也无法释放,因为呢,它无法再从这个位置继续往下执行了,他只能接受新的请求。那么这个拉锁呢,就一直存在着啊。出现思索问题了。这就思索问题。那么,怎么去解决这种思考问题呢?我们就给锁呀。添加过期时间。哎,时间到了,让它自动释放就可以了。那比如说他可以添加一个三秒或者30秒的过期时间。那怎么添加过期时间呢?在我们的指令里面啊,也给他提供了dinner指令。
03:04
好,我们可以去演示一下。比如说呢,我们release里面啊,可能提供了叫啥呢,叫P,那么这样的一个指令,那它可以给一个K设置一个秒级别的过去时间。那么也有对应的,好像对应的这个PXK啊PXP,它也可以给个K来设置一个毫秒级别的国际时间,那更加精确。那其实呢,我们这里呢,没有必要搞那么精确,比如说咱就来一个秒级别的普及时间。那咱可以使用呢,使用这个XP啊,这个指令啊,那我可以呢,先去set一个,给我来一个log索来个111这样子。然后给这个K呢,设置过期时间,来一个ST啊,比如给这个lock所设置一个20秒的过去时间,那么20秒之后。那锁呢,就过期了,一旦过期它就会自动释放掉。我们可以看一下啊,来一个TPL让查看锁的过期时间还剩九秒钟,那我们继续运行,还剩七秒,还剩五秒,还剩五秒,诶我这手速还可以啊,那么然后时间到了之后呢,又变成负二了。
04:11
一旦变成负二,那么这个lock所还存不存在呢?我们可以看一下来一个get请求,然后呢,是lock,那已经没有了。啊,已经不存在了。那不存在之后,那么后续的其他的请求就可以从我们健康的节点服务上或者服务节点上,然后来去获取我们的锁。好子弹设置获刑时间,可以防止搜索。那么也就是说呢,防止死锁呀,我们可以通过设置过期时间来去防止死锁啊,那么这种死锁现象怎么去描述呢?一定要先给你描述一下啊。OK,那么如果咱的red客户端客户端程序,哎,什么是red客户端程序呢?比如说呢,我们的这台,我们的这个这个服务就是一个release客户端程序,对于来说它是一个客户端程序。
05:07
那么然后这个服务二对来说也是一个客户端程序。好,那么如果我的客户端程序从中获取到锁之后,对吧,那么从RA服务中获取到锁之后,那么然后立马宕机,立马宕机就可能会引发搜索。那么怎么解决这个死锁问题呢?解决怎么解决呢?咱可以给所添加过期时间,怎么来解决?那么给所添加过去时间,那我们刚才呢啊,咱可以通过通过这个XP这个指令,那么来添加过去时间。哎,那我们可以去通过代码来实现一下看看啊。那比如说呢,咱这里呢,如果一旦获取锁成功了,我在执行业务逻辑之前,我就去设置过期时间了呀。那假如说我在这个地方一设置啊,来一个x.ready点上呢,它有这个XP这个指令啊,你给一个K,那么来去设置过期时间,那比如咱也可以给这个lock所设置过期时间,那设置多长时间呢?比如设置一个那么30秒的过期时间。
06:19
或者呢,就三秒的攻击时间,应该一般也够了啊,来一个time unit可能是了。该设置好了呀。那现在它可以防止搜索了吗?哎,不能防止。为什么不能呢?因为我可能一个请求过来,刚刚执行完这行代码,汇到所支行代码之后呢,还没来得及执行这行代码呢,那那服务器就已经宕机了。那么此时你这样设置还有意义吗?就没有意义了啊。但是呢,渔业公司呢,就这么设置的。哎,我就看过一个每一个互联网公司啊,啊就这么写的。
07:01
OK,那么但是呢,还是有有问题的啊,我们要追求什么呢?要追求完美的,对啊,追求完美。OK,那我们来去看一下,那么既然这种方案啊还是有缺陷,那咋办呢?哎,这是什么缺陷啊?哎,是因为我们获取锁和过期时间之间没有原子性导致的啊。导致的,哎,我这里呢,虽然获取锁成功了,但时间还没来,没没来得及设置呢,那中间就挂掉了。所以我们还应该怎么样呢?还得要考虑原子性问题。所以在锁呀,我们在实现分布式锁的时候,首先我们要保证分布式锁自己的操作要具备原则性。那么第三个特征要保证什么?保证原子性操作?那么咱这里的话呢,是第一种情况啊,就是我们获取所和过期时间之间要保证原则性。那怎么保证呢?
08:01
好,那我们呢,其实有一个指令啊。既可以设置过期时间,又可以获取锁。啊,就这个指令了。那么三的指令啊,咱平时用的比较简单啊,那么其实呢,它是有一点点复杂的,那你可以设置key value,这是常规的参数啊。还有可选的参数。你可以通过exx来设置秒级别的过期时间,你也可以通过PX来设置毫秒级别的过期时间,那最后呢,还有什么呢?还有这个NX和这个叉叉。啊,N叉和叉叉,那么N叉相当于什么呢?就相当于塞塔等于X。那么这个叉叉呢?就想呢,就是啊取反了,这个NX相当于不存在,那我就设置。那么这个呢,是存在我才去设置。就类似于我们之前看到的这样的一个方法,有一个叫点上的set if print这个方法,哎,这个底层呢,就是叉叉,这个底层呢,你看就是那个NX啊。
09:04
那就NX好,那我们呢。来看下这个指令到底怎么去玩嘛。那比如说呢,我可以去获取一个log锁,那么值呢,我都无所谓,也就来一个111,然后呢,我可以通过ex设置一个秒级别的过去时间,也就设置一个20秒的过去时间,那再来一个呢,再来一个0.x,如果不存在我才一设置,那如果是叉叉呢,就如果存在我才一设置。那么此时lock存在吗?不存在,那不存在,我使用叉叉能设置进去吗?设置不进去啊,来我们看一下你设置失败了啊,你只你来一个get lock,你可以看到设置失败了没有。那说明叉叉,那就啥呢,就是如果存在才设置。那么它换成这个NX哎,它就可以执行成功了,诶此时呢,我的lock是不存在的,那我刚好呢是不存在,我就设置,我就回车,你设置成功了,来看下这个lock啊。
10:02
他已经在这个里面了。那么还剩多少过期时间呢?你可以通过TTL让lock查看一下,还剩十秒钟,那么还剩八秒。啊,六秒啊,然后呢,我们来看啊,那么时间到了,时间到了之后呢,我们来一个get lock,它已经没有了。啊,自动释放锁。那么如果我们是同一个指令,哎,它在ready里面就可以保证原子性。那的话呢,只要同一个指令啊,它一定是具备原则性的。好,那我们就可以用这样的一个东西,那么来去实现。那么然后在代码里面怎么体现出来呢?但其实体现出来很简单,那我们这个东西啊,就相当于塞啊,然后呢,最后来一个NX这个指令啊。那么你除了可以设置key value,还设还可以设置什么?设置过期时间。那么你看这个方法其实还有其他参数呢,咱们可以看一下。
11:02
另外还有可能还有过期时间这样两个参数啊,多长时间单位是什么。比如说呢,我可以设置一个三秒的过去时间,那么时间单位啊是秒。哎,那我们这样呢,就设置好了。啊,那么它既可以防止死锁啊,又可以保证我们的原子性。
我来说两句