00:00
好,刚才呢,我们分析了一下主射手的实现思路是什么样子的。那么首先呢,咱其实做锁呀,啊,分成了三步啊,三步啊三步,那么第一步呀,我们所有啊,请求啊,要求获取所值,获取所值,我们来者不拒。那咱就给每一个请求来去创建临时序列化。序列化节点。那么虽然基点创建出来了,但是呢,它不一定能获得到所。那咱们要有第二步了,紧接第二步呢,我们要去获取当前节点的前置节点。前置节点啊,那么如果前置节点呃为空,这个前置节点是比较小的那个节点啊,给它小一的那个节点。前置节点。
01:00
节点那么为空,那么。则获取所成功,那说明已经没有比它小的节点了。那么否则我们可以监听,那么前置节点它是第二步。那么然后呢,我们这个第三部分呢,就是我们执行呃,业务成功会所成功之后啊,执行业务逻辑获取所成功,成功之后来去执行业务操作,那么然后呢,啊再去释放,释放当前节点的这样的一个锁。好,那我们来去实现一下这样这样的一个步骤,那么刚才呢,我们已经把代码呢,写了一部分,那么这一部分咱们在实现了一个第一步的一个过程啊,就这句话啊。那么我们来创建一个临时虚拟化节点。然后呢,嗯,就是这一步嘛,给它放在啊这个地方,那么然后呢,我们来去获取前置节点。
02:06
那么前置节点如果为空的话,那就可以获取所成功了啊。好,我们可以来一个,到时候我们可以进行判断,对吧,进行判断。那当然这个判断的话呢,没有那么简单啊。OK,那么然后呢,我们呃,这个地方自选啊,咱后续呢就不需要了,我们可以给它注释掉。那么将来我这边释放手的时候,哎,我就肯定肯定不能这样去释放了。啊,应该释放谁呢?释放当前这个节点的这个节点路径对应一个节点啊。那么这样来的话呢,我们为了好判断呢,咱们可以在这个所的名称后面呢,加一个加一个杠,那么这样的话呢,呃,咱的序列号和所名称之间呢,啊,就很好分割了啊。啊,很好分割开了。好,那么将来我去释放的时候,要释放这个全路径对应的那个节点。那么咱咱们应该最好给它设明到这个外面去啊。
03:00
那这样的话呢,我在释放那个方法里面就好去使用它了啊,来一个spring,它是current。Current是no pass这样一个玩意儿。啊,那么然后呢,我们在这个地方啊,咱就不需要去证明这样的一个嗯,这样的一个类型的数据了,啊,直接给它删掉,那么然后呢,我这释放所的所谓啊,我就释放这个current not pass就行了。啊,那么执行完业务投资之后呀,等于释放当前这个节点,对的路径啊就可以了。好,然后呢,我们来去看一下啊。啊,咱这个方法该怎么去实现,我们创建这样的一个方法,那么这个方法里面啊,呃,怎么写呢?首先第一步我们肯定要去获取,获取根节点下的所有节点,那我才好去判断我是不是最小的呀。那么根据点下的所有节点怎么获取呢?我们就类似点,然后keep点上,然后是get toing,那么这个路径啊,咱们是那个root pass2个路径根节点下面的所有子节点嘛。
04:08
然后呢,咱们的参数呀,还需要这个监听啊,咱这里呢,也不需要什么监听,我只要获取所有的子节点就可以了。那么啊,有异常啊,我们可以直接去处理一下啊,咱们可以来一个嗯,Try catch。好,那么然后呢,呃,我们呃,拿到这个所有节点之后呀。那说如果这个地方出现异常啊,出现异常咱们可以去给他合并一下这一块啊。啊给删掉合并一下来,咱就获取那个最大的那个异常嘛。合并一下,那么出会出现异常,我们可以直接去抛一个,反正你有一个什么呢。哎。A logo然的是mon,然后不行。那么这也是我们可同入所里面经常用到的一个异常啊啊,就是错误的监听状态异常。OK,那么你都没有这个,你就没有前一个节点了,或者出现异常对吧,咱获取前个节点出现异常了,那说明呢,咱这个呢,可能是一个非法的一个操作啊非法操作,那么一般情况下对吧,要么呢,你前个节点为空。
05:13
那么你没有前一个节点,那么要么的话就是你就有前一个节点的,那结果获取前个节点出现异常了,那这怎么回事呢?咱就属于一个非法操作吗。OK,那么这里面呢,咱们来去啊看一下啊,为了保证变异通过这个地方,可以先水平一个nu在这个位置。啊,那么首先呢,我们来去判断,那么这个根节点下面的子节点。哎,是不是为空,如果这个根根基点下面的极点,所有据点极点为空了,哎,那这也是一个非法操作呀。哎,怎么会,怎么可能会空了呢?因为我刚刚创建了一个临时节点都对啊,结果发现它会空了,那这应该是不可能的一个时间,但是呢,为了延谨起见啊,我们还是去判断一下啊。啊,咱们可以适当的使用这个莱新。然后是UUS啊,点上呢is input啊,如果子节点为空的话,那我们可以直接去也抛一个啊异常哈,那么这个异常呢,咱可以直接拷贝过来,让它放在那么这个地方。
06:11
啊,那么呃,这个呢,一般情况下肯定是不会空的,那咱为了严谨起见啊,判空了一下。啊,那么他这的话呢,呃为空,那说明这是一个不可思议的一个操作啊,反正就显示一个非法操作嘛,那如果不为空的情况下。那我们怎么办呢?我们要获取。当前当前这个资源的锁耗当前资源的锁,那比如说我的库存可能有多条库存记录。那为了防止超卖,每一个库存记录呀,可能都有自己的分布式数啊。那比如说呢,我这个库存,嗯,ID等于一的这个库存,然后呢,我可能使用这个lock lock lock差这个锁。那么然后呢,还有ID等于二的这条库存,它也可能会发生超卖呀,那我可能有一个什么lock等是Y这个数。
07:00
那么然后呢,我还有ID等于三的这个,呃,这样的一个库存,那对应的可能有个lock z这样的一个锁。啊,那么这个锁呀,啊,这是不同的锁啊,不同的锁他们之间会相互影响吗?不会的。但是呢,这个lock差开头这个锁呀,就能相互影响的啊,那比如说在我们这个里面就是这样子的啊,可能呢,我对这个啊库存库存ID等于一的这个仓库有一个呢,有一个呃杠一杠S,然后一个log,然后杠log X开头这样的一个锁。那针对这个I等于一的,我有log差这个符号。那么针对ID等于二的,哎,我可能会有呃,Lock,呃,Y这个锁啊,Lock y这个锁,那么然后呢,我这个也是一样,哎,Lock X y,对啊,XY了,假设ID等于二的这个库存,我们有一个log X y这个数。那么这两个所之间应该应该相互影响吧,不应该相互影响。
08:00
那比如说此时lock X y,它呢,有一个线程可以获取到这个数,那同时lock X,那么这个48,这个还可以获取lock lock X的数。那么他们俩呢,是相互之间没有影响的,因为他们操作的是不同的库存资源。他们是可以并发的啊。OK,那么我们这的话呢,主要去获取同一资源的锁,获取当前什么节点,和当前节点,同一资源的锁啊,和当前节点。那么同一资源的。同一资源的。那么所。那么然后呢,我得要去获取同一资源的所比自己小的对不对啊。比最小的就前一个节点嘛。那么当前节点同一资源的就是所的名称一样的,对不对啊,所的名称一样的。好,那我们这的话呢,怎么获取呢,那所有词点都获取到了,有没有跟我是同一个资源的呢。
09:00
咱们了解过滤组统一资源的啊,来一个啊秋瑞,那我们可以使用string表达式点上是的过滤。那么然后呢,在这个里面啊,咱们可以来一个漏表示箭头函数,那么然后呢,咱们来判断怎么判断。What,要根据这样的一个呃前缀来判断就可以了,那比如说我这个资源的,比如说以lock down开头的。那我这个资源呢,肯定都是以log X开头的。那么另外一个资源的可能是以lock lock X y开头的啊。开头的。那我们这个呢,咱可以呢啊,通过这个string是U。是跟哎导包应该导错了啊,不要去使用那个spring里面那个。呃,频U啊,因为这个呢,嗯频啊很垃圾啊。那我们这个地方呢,咱可以来一个点上。然后呢是呃,咱应该是string上是us是long sample下面那个啊,点上的是start with。
10:01
那么看看我们这个节点,归类出这个节点是以咱们这个lock name同一个lock name开头的,那我们这个锁呀。呃,不同资源的所所的名称是不一样的啊,看看你是不是以我们这个lock name开头的,那基因是lock name的话还不行,因为的话呢,我们这个lock呢,我这个是lock name是lock,那他的lock name是lock,呃,X,它的这个lock name是lock X y,对啊,也都是以lock开头的。因为这个节点啊,都是以log开头的啊,以log开头,以log开头,以log开头。自然仅仅以log开头肯定是不行的,那么你还得要加上呢,加上一个呃,是吧,那么这样你可以定位到我们同一资源这个锁了,如果我加上这个杠的话,你可以定位到啊同一资源的锁了。那这也就是为什么咱创建临时定点的时候呀,因为我前面加了一个杠。他刚刚加的一个刚啊。啊,就是为了呃,过滤出方便过滤出我们同一资源的锁。
11:01
那么然后呢,变成一个新的集合啊,收集成一个新的集合,使用收集器啊,获取到同一之间的锁集合了啊好,那么咱一来一个NOTDE4啊,这就可以了。那么这个no里面有没有比自己小的呢?好,我们再去获取比自己小的之前啊,咱可以先去排队啊,先去排好序。排好序,那这样的话呢,就很好判断了,排好排好队对吧,这样子。那么注意啊,咱们在排列之前啊,一定去判断一下,哎,同一资源的锁是有可能为空的。啊,那我这个根基点下面可能有很多子节点,但是呢,可能都没有当天锁的这个。锁这个这个节点啊,可能没有当前所这个节点的当天所锁定节点的啊,定的节点。那所以的话呢,咱对当前所的节点啊,这个集合呢,也要去判空一下。啊,严禁起见的话啊,那再再去判空一下啊,来一个collect,嗯,可点一下啊is,然后是来一个noodles啊,如果它为空,我们也是直接抛出一个异常。
12:06
对吧,你同一同一资源的所压根就都不存在,那这种情况可能吗?不可能,因为我刚刚创建了一个临时序列化节点。就当天这个资源的临时去哪节点,结果你没空了,那这也不可能啊,所以呢,咱也就抛出了异常。啊,那么然后呢,如果不为空,我们对这个集合呀,啊排队啊排队怎么排队呢,咱可以使用这个来个星。来一个信行思啊这样的一个工具类,那点上呢,是有so的一个方法啊,对我们这个node节点啊,它进行排队。那排好队之后啊,我们来去获取前前一个节点啊,咱们可以先去获取当前节点的节点,这个下标节点下标,如果当前节点下标等于零的话,那说明我当前节点就是第一个节点。如果当前节点的下标不等于零呢?那我们可以获取那个上一个节点的,就下边减一那个节点的。
13:04
就可以获取前个剂量了呀。好,那我们这个,嗯,当前基点下面怎么获取呢?咱们可以使用这个。那依然可以使用这个collection里面的,然后它里面有一个什么bary色写的这个方法。哎,那通过这个方法呀,我就可以获取咱们集合里面的某一个节点的啊,某一个节点的在能下标。好,那么这样的话呢,我就可以把a current past给它放进去了,这里要注意了啊。那我们这个noodles,它会是什么东西?它获取的不是全路径,它获取这个东西啊,比如说呢,我们来一个来一个los,然后杠啊是lo lock lock lock,然后是OE回车,他这呢,你该获取的这个这个节点,你这是输入节点。它这是全路径吗?不是全路径,但是我们之前创建节点的时候呀,我们返回当天节点,这个当天节点的是一个返回这个全路径啊,返回的当天节点是一个全路径。
14:02
而我们拿到这个节点列表的时候呀,它不是一个全固定,它只是当前节点的一个节点名称。不是全路径。那所以的话呢,我们如果直接这样去做的话,是获取不到的。因为它是全路径,那它里面的话呢,都是当前基点名称啊,所以呢,我得要从当前基点全路径里面让它获取出当前基点的名称,那我要获取的是什么东西呢?哎,是这个东西。哎,比如说这是当前节点,我要获取当前节点名称,那怎么获取呢?其实这个东西呢,也很简单啊。我们只要获取最后一个斜杠。那我这个路径有几位你也搞不清楚啊,当然的话咱是可以搞清楚了,因为咱这个有有根据点嘛,这啊根据点下面的这样的一个东西嘛,那其实呢,我可以就获取最后一个斜杠后面这个内容就可以了,我可以截取最后一个斜杠后面的这个内容。就拿当前机理名称了。那么我们啊,这个位置呀,呃,获取前一个节点的时候呀,咱们先去获取。
15:05
啊,那个当前几点的名称。那咱可以使用string us,然后呢是sub string是after last。I翻什么意思呢?就是子字串嘛。啊,就是嗯,最后一个,最后抹抹一个什么东西,后面的一个东西。对吧,那我要截取这个字符串里面的。啊,最后一个这个分割符,后面这个内容。好,那比如说我要截取当前这个节点全路径,然后最后一个斜杠后面的内容。啊,最后一个斜杠后面内容,某一个东西后面的内容。啊,最后一个什么东西,后面的内容对吧,那最后一个斜杠,然后后面的那个内容,那就可以汇到当前基点名称了啊OK,那么这当前基点名称啊,是咱这个来一个current是note,那就叫current note,那我要获取当前这个基点的下标就可以回答了。
16:06
好,这呢是获取获取当前那么节点啊,那么然后呢,我既然可以获取当前基点的这个下标了,那下标的话呢,返回值呀,啊是一个啊in那个玩意儿。好,那我们就可以判断这个index了,那么如果index那么小于小于零,那说明呢,咱们这是一个也是一个非法操作啊,那我们也可以去抛出一个异常非法操作,非法的所操作嘛。好,那么如果if啊if,那么如果咱这个index如果大于零,那说明我们当前节点就不是第一个节点。那咱要返回上一个节点,那此时呢,我们就可以去ta上一个节点,上一个节点呢,应该是呃,这个no。No,点上get是index减一啊,这就获取前一个节点了。
17:05
它这呢是返回,那么前置节点啊,就前一个节点。那么然后呢,如果你等于零的话,那等于零的话呢,我就返回一个,那那返回none的话呢,就代表代表是啊,我们没有前置节点,那我就是第一个。这我就第一个,这就反一个那吗。它这样就可以了呀,对吧,那么如果啊,如果那么当前节点,那么就是第一个节点,那么则返回,那么那对吧,返回那就可以了。那么这个时候呢,咱们这个get no的这个方法呀,我们这已经封装好了。那封装好之后呢,那我们来去看一下啊,这个前置积点呢,已经拿到了。那难道之后要注意我们这个地方获取前置积能的时候呀,因大写了大量代码来就说的,因为这一块有原子性吗?哎,没有原子性。
18:01
那么可能你再去获取前一个节点的过程中,那么前一个节点就已经把锁给释放掉了。所以呢,我们这个地方啊,要再次判断一下这个前置地点是不是为空啊。那是不是围控,因为你在获取过程中呢,可能前置节点已经拿到锁,并且呢,已经释放锁了,都已经不存在了。好,我们这地方呢,呃,绘出这个节点之后呀,进而呢,他就要做进一步的判断。那么首先的话呢,这个咱过到前置节点没有呢?他有没有前置节点呢。那如果嗯,不等于,哎,那对吧,如果你的氢节点不等于空,然后呢,我就要再判断一下组K里面是否存在啊,那么呃,再次那么判断ZK中的这个前置节点,前置点是否是否存在。是否存在,为什么要再次判断呢?啊,因为啊,因为获取前置节点,那么这个操作那么不具备不具备原则性。
19:02
那么你可能在获取潜水进水的过程中,那其他它已经获取到所了,并已经释放掉了,现在需要再次判断一下。啊,那么这个地方呢,呃,如果前置一点不等于空,我们需要去再再次判断一下啊。那如果它等于空呢?那等于空,咱们就直接获取所成功了吗?当前节点就算就是第一个节点,你可获取所成功了,如果前置节点呢,不等于空,我们要看看它是不是还存在。那如果存在。啊,如果存在,那我们要监听前一个节点,如果已经不存在了,那我们依然可以获取所成功啊,一个处就可以了。那我们可以呢,来一个A判断。那么这地方呢,还可以来一个普啊,来一个啊,This点就是呃the keep啊the keep点上啊是this,可以判断是否存在。那么前置节点呢,应该是root。有pass,那么再加上。啊,加上一个斜杠,然后再去加上咱们这个noodle啊前置节点。
20:04
那么是否存在对吧,那这个地方呢,咱还有另外一个参数啊,那这个参数呢,是监听参数,咱可以用一个what a监听。啊监听对吧,那如果它等于空。如果这个地方等于,那么那对吧,如果这个is这个方法呀,它反应值等于no,那说明什么?说明咱前置节点已经不存在了,那前置节点已经不存在了,那我不就第一个了,我前面一个已经已经已经没人了,我前面已经没人了,那我就第一个呀,四你可以这句水平一个处啊或取所成功了啊OK。好,那么如果呃,我们这个存在呢,存在呢,那我这个地方你要有先听着点啊。我得要去,呃,监听它这就那个监听时间嘛。OK,那么一旦我这个地方。这地方监听到了,那我这地方应该也是应该出。对吧,也着个出啊。啊,大家要去使用好呢,使用这个闭锁来去保证原子性了。
21:02
那我们可以在这里呢,去呃,加上这个闭锁啊,来nu一个就是countdown large来设置为一嘛,对吧,设置为一,那么来个countdown啊这样一个对象,然后呢,在这个地方啊,我们去来comedown点上的是a wait,那么如果我这个地方没有监听到,咱这个地方应该一直阻塞着啊。一直阻塞。这。那么一旦我进行到了,那我可以怎样看到large点,让这是countdown方法来进行减一?那么减为一减减一之后呀,除非减为零了吗?减为零之后呢,我这里可以放行,放行之后呢,就可获取所成功,当天基点就可以获取所成功。当前一个节点呢,释放锁之后呀,咱这个地方呢,就可以放行了啊,就可以放行了,减一之后呢,就可以放行。当天几点可以回答说?好,咱利用这种闭锁思想。啊来去啊,实现这个阻塞功能啊,OK,那么利用利用这个闭锁,那么思想。
22:00
呃,来去实现这个阻塞功能。那么如果我前一个基点没有触发这样的一个监听事件,它一直阻塞着啊。直到前一个节点释放过之后呢,这个地方呢,会触发监听,然后呢开始去减一,减为一,减一减一之后呢,就减为零了,然后呢,火炬说间节点。啊,咱们这个代码呢。那就已经写好了。那么像。
我来说两句