00:00
也就是说,我们通过set key value加一个过期时间,然后以及NX,就可以成功解决了原则性问题。那么我们的锁还有没有其他问题呢?我们可以结合代码来去看一下。那么另外一个问题呢,就是我们的过期时间可能不够。我们设置为三秒,你那么设置为30秒,300秒也有可能会不够。你设置在场都有可能会不够。啊,因为呢,比如说呢,我们的服务发生GC啊,或者呢,啊发生了一些抖动,或者某一环节呢,被阻塞住了。那等了很长时间都没有执行完。那么如果我们不管不顾,直接时间到了把给释放掉的情况下,那么咱剩下的业务逻辑呢,就处于裸奔状态了。好,那我们举个例子啊,举个例子,那么假如说呢,我们设置的过期时间就是三秒,一般情况下肯定就够了。那么假如说啊,我这里呢,有一个请求需要五秒钟才能执行完。
01:03
那我这呢,画一个草图,每一条线呢,代表是三秒钟啊,那我可以呢,多画几条线。多画几条线。那么假如说呢,我此时有一个请求过来,那么这个请求呢,处理过程啊,需要五秒钟啊,那五秒钟呢,执行完。但在执行第三秒的时候,由于我的过期时间是三秒钟,那第三秒的时候呢,我的锁呢,就失动自动释放掉了。那么释放量之后,那么第二个请求,于是呢,就可以获取到我们的所。他也需要五秒钟。啊,假如说都是五秒钟啊。他也需要五秒钟。但是它执行到执行到第二秒的时候,就会怎么样呢?我们的锁就会被第一个请求给释放掉。因为第一个请求啊,会通过de指令,D指令来去释放我们的lock锁,删除这个lock锁。但这个log锁现在属于谁呢?属于第二个请求的,它属于第二个请求的。
02:02
好,那么我们第一个请求呢,就会把第二个请求呢的所给释放掉,那么产生了这种误删啊,产生了这种误删。好,那我们来继续分析,那么假如说呢,我们第二个请求啊,被第一个请求所释放掉之后啊,那么第三个请求又来了,那他获取所成功,那也需要五秒钟执行完。那么然后呢,五秒钟哎,到第三秒的时候,那么锁呢,就会自动释放掉,那么释放掉之后啊,第四个请求于是回到锁了,那回到所之后啊,那么很不巧,因为第二个请求呢,此时执行完了,他开始执行第二操作。来句释放所,那它释放了谁的所呢?是第四个请求的所。第四个请求可能刚刚获一道锁,就被第二个请求给释放掉了。那么全程就处于裸奔状态了。那么然后呢,我们第五个请求,于是就获取到锁了,最后呢,就会出现咱有锁和无锁呢,没有什么区别了。
03:05
导致我们的所提制失效。那么这里呢,其实是有两个原因,两个啊问题啊,一个问题呢是误删问题,而我这个请求不能把其他请求的锁给释放掉,你只能释放自己的所。所以呢,我们要去防雾山啊。那么第二个问题呢,就是呢,过期时间可能会不够。如果我能够做到自动续期就好了,对吧,自动续期。哎,就好了。好,那么咱这话呢,有同学说,那你自动续期了。那我还要设置过期时间干嘛呢?那他们会不会有矛盾呢?哎,其实不矛盾啊,那我们呢,可以先把这两个呢记录下来,那我们的非木质所呢啊,还得要去做到这两个特征,第四个特征呢,是防雾山。哎,我们有一句话说的非常好,叫解铃还须系铃人嘛,对吧,还需系铃人啊。
04:02
那谁谁谁系的零,那谁能解,你不能把别人的零呢给解掉了。你不能把别人的所能给释放掉了。好,那么第五个特征,那么是自动续期,自动续期和我们的过期时间之间会不会相互矛盾呢?啊,其实呢,不矛盾啊,甚至过滤时间的目的呢,是为了防止服务器宕机而带来的而带来的死锁问题。那我们呢,自动续期怎么回事呢?那么自动续期啊,是为了防止咱的请求,咱的业务逻辑还没有执行完呢,然后呢,时间就到了。导致我剩下的一段业务逻辑裸奔,那产生一些并发性的问题。那我们的自动续期也需要借助什么,借助于我们的程序来监听,来监听啊,监听我们的业务逻辑有没有执行完,如果没有执行完,我们要不停的给他去加长这个时间啊,延长这个时间。
05:05
OK,那么他跟咱的过期时间会不会冲突呢?不会冲突。因为呢,咱的过期时间是为了防止服务器宕机带来的搜索问题,你想如果服务器都已经宕机了,还会自动续期吗?啊,自动续期呢,咱后续也会通过程序来自动续期啊,那如果服务器都宕机了,那续期呢,自然而然的它就会终止。那么一旦终止了咱们的这个自动续期呢,就不会再续期了啊,那么然后时间到了呢,咱的锁就会自动释放掉。所以他们之间不矛盾。那么还有呢,是防误删,那防误删怎么回事呢?哎,永远都不过期了,还会误删吗?有可能会误伤,那比如说呢,咱在re lock里面。人称lock里面你可能呢,从来没有加过锁。
06:00
可能从来没有通过lock方法加过锁,哎,就直接干嘛呢,通过unlock可以解锁了。啊,你可能会恶意去释放锁啊,从来没有加过锁,就只解锁。但是恶意释放左呀。那为了防止别人恶意释放锁,我们要去防止啊误删,防止别人恶意释放锁。你可以认为。那么这是别人不是恶意的,那比如说呢,有一个啊,技术不太成熟的一个程序员,他写了一个代码。然后呢,Lo它加锁了,那unlock也解锁了,但因为程序写的不对,锁了都没有加上,结果呢,最后呢,来一个unlock。还去解锁?如果我们不加以限制的话,就可能会导致误删。但在软lock里面会误删吗?不会,他做到了防误删。好,那我们也是一样,我们只要防止别人去啊,误删我们的锁啊,不管是恶意的,那么还是无意的啊,咱们都需要去防止一下。
07:03
接下来呢,我们来看一下怎么防雾山。那删除锁之前,你首先得要去先判断再删除啊,先判断是不是自己的锁啊,再去删除,所以呢,咱们要去先判断,那么再删除。好,那我怎么判断这是不是自己的锁呢?我怎么设置是不是我的呢?因为所有人的所所有请的锁,只要执行这个方法,它都叫lock。他怎么知道这个是不是自己的?好,那么咱们表语加一个唯一标识了。那比如说呢,我可以给每一个所搞一个唯一标识,比如说你可以是现成的ID,那么你也可以啥呢?你也可以是什么UUID,那么搞一个。找的所的UUID啊在这个地方。然后呢,沉到哪里去呢,我可以给它放在value这个位置,因为它的value呢,还没有利用起来。
08:00
给它放进去。将来我去释放所的时候,那我可以呢去判断一下。哎,那我当前请求的那么UID,那么和我ready这个UID和这个锁的UID是不是一样。和这个value是不是一样。如果一样的话,说明就是我的错。我才能去释放所。那我们就可以给每一个请求啊,来去添加一个UID了,来一个UUID。啊,这样的一个东西点上呢,Get,点上random与点to stream,它变成一个组上类型的。好,那么这个UID呢,唯一标识我们就生成好了,那么生成好之后呀,咱可以给它放在我们value这个地方,保存到我们的数据库。那保存进去之后呢,我们在解锁的时候,咱就要去先判断那这一解锁了。啊,大家去先先判断是否自己的锁,然后呢再解锁啊。
09:02
那么判断自己的锁,我们都要去查ready呀,我们要来一个this意思点ready time白点上option for value,点上get,我看一下这个lock所里面的这个值,哎,是不是等于我当前的UA,那咱可以呢,使用equals来判断对吧?啊,那咱这里呢啊可以呢,使用很大使用词spring还是us。好,我们好像没有那个浪三包,那没有那个浪三包呢,咱们可以引入一个浪三包啊,来一个底盘的意思,然后是浪三啊阿瓦提的浪三包。好,那么引入进来之后啊,我们来去看一下我们的应用程序,在应用程序里面我们可以使用string啊us。啊,那么应该导入进来了,Spring,然后U。浪三的这个包啊,点上呢是一。让release里面这个UID和我们的当前请求的UID是不是一样子的,哎,如果是一样子的,那我才能去释放这个锁,如果不是的,如果不一样了,我能去释放所吗?
10:12
我就不用在意释放了,说明自己的所呢已经不存在了,可能已经自动释放过了。啊,或者说自己的所能压根就就不存在,你就不能去释放。好,那么这样的话呢,咱改造好之后呀,它就可以防误伤了啊。那这个测试我们就不打算测试了,因为呢啊肯定是没啥问题的,你们可以自行测试一下啊。
我来说两句