作者:微信小助手
发布时间:2022-03-02T13:39:39
在分布式系统中,由于 redis 分布式锁相对于更简单和高效,成为了分布式锁的首先,被我们用到了很多实际业务场景当中。
但不是说用了 redis 分布式锁,就可以高枕无忧了,如果没有用好或者用对,也会引来一些意想不到的问题。
非原子操作
if (jedis.setnx(lockKey, val) == 1) {
jedis.expire(lockKey, timeout);
}
容易,三下五除二,我们就可以把代码写好。这段代码确实可以加锁成功,但你有没有发现什么问题?
加锁操作和后面的设置超时时间是分开的,并非原子操作。假如加锁成功,但是设置超时时间失败了,该 lockKey 就变成永不失效。
假如在高并发场景中,有大量的 lockKey 加锁成功了,但不会失效,有可能直接导致 redis 内存空间不足。
那么,有没有保证原子性的加锁命令呢?答案是:有,请看下面。
忘了释放锁
上面说到使用 setNx 命令加锁操作和设置超时时间是分开的,并非原子操作。
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
return true;
}
return false;
其中:
lockKey:锁的标识
requestId:请求 id
NX:只在键不存在时,才对键进行设置操作。
PX:设置键的过期时间为 millisecond 毫秒。
expireTime:过期时间
set 命令是原子操作,加锁和设置超时时间,一个命令就能轻松搞定。nice!
使用 set 命令加锁,表面上看起来没有问题。但如果仔细想想,加锁之后,每次都要达到了超时时间才释放锁,会不会有点不合理?加锁后,如果不及时释放锁,会有很多问题。