就事论事

就事论事系列-时间格式的处理

2021-03-08  本文已影响0人  大师艾小伦

我们在处理业务的时候,有时会需要控制业务串行处理,如果是同一个jvm,我们可以通过java的并发关键字 synchronized 来控制。但是,目前我们的系统基本都是分布式系统,同一个服务是多台机器同时提供服务的。这个时候分布式锁就是必需的了,我们使用Redis分布式锁,下面我们就来聊聊他的使用方式,以及使用的时候需要注意什么。(画外音,可以少踩坑哦)

图片

Redis分布式锁:
SETNX SETNX key value将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。可用版本:>= 1.0.0时间复杂度:O(1)返回值:设置成功,返回 1 。设置失败,返回 0 。


使用该命令时,我们需要注意的一些点是:

  1. 该命令实际是设置了以key-value对在redis服务器上。因此,在锁资源访问结束之后,该key-value对是应当被删掉的。

  2. 删的过程也有可能有意外,因此,最好要设置一个过期时间。

实际应用中,我们代码可能是这样使用的:

//尝试设置cachekey看是否能设置成功,设置成功,返回 1 。设置失败,返回 0

为了保证删除key的操作一定会被执行而不被执行业务中的可能的异常打断,我们应该使用try-catch-finally的方式,将释放锁的过程放在finally中。

我这里有一个使用的例子

try {

这个例子的确这样使用了,但是在实际应用中发现,这样的锁有时候会失效。

***[图片上传失败...(image-5ae141-1615193359066)]

锁被意外地释放了?******[图片上传失败...(image-2776d8-1615193359066)]***

经过分析以后才知道:

  1. 当有三台机器同时并发处理的时候,由于其中一个通过setnx 获取到了资源锁,进入逻辑处理阶段。
  2. 另外两个当中的一个进入了try块,通过setnx执行没有获取到锁,于是退出了,但是由于已经进入了try控制的代码块 ,导致异常机制中finally里面的代码必然会被执行 ( CacheUtils.del(cachekey) 这条语句被顺带执行了)。
  3. 剩下来的那个,又可以稳稳当当,好像没有人跟他并发一样将事情顺其自然地给做了。

明白了问题出在哪儿,大家考虑一下怎么解决呢?

其实我们该做的就是需要加一个自己是否获取到锁的标记,如果自己没有获取到锁,那么此时就不应该将该锁释放掉。问题解决

boolean lockedBySelf = false;

总结

今天就聊到这,就事论事,就看我们的代码里面的事。如果觉得还可以的话,关注一下。

上一篇下一篇

猜你喜欢

热点阅读