Redis作为一种常用的缓存系统,具有高速、可扩展性强的特点,常用来进行分布式锁的设计。在Redis中,有三种不同的实现分布式锁的方式。
方式一:SETNX
SETNX是Redis中最为原始的实现分布式锁的方式。其本质原理是使用Redis的SETNX(SET if Not eXists)命令,去尝试获取锁。
代码实现如下:
SET key value EX seconds NX
其中key为锁名称,value为随机字符串,seconds表示锁的过期时间,NX表示只有key不存在时,才会成功执行SET命令。
这种方式的好处是简单、易于实现。但是不足之处是,如果在SETNX成功获取到锁后,在unlock之前出现程序异常或者运行时间过大导致锁过期,就会出现锁被其它程序抢占的情况。
方式二:SETNX和GETSET
为了解决方式一出现的问题,出现了SETNX和GETSET的组合使用方式。
代码实现如下:
SETNX key valueGETSET key value
首先使用SETNX尝试获取锁,如果返回成功,则执行GETSET命令,即设置新的随机值,并获取上一次的值。然后我们再看上述代码后面可不可以加一个比较操作,提供一种解决缺点的思路,即:
if (preValue == curValue) ret true;else removeLock(); ret false;
这种方式可以解决方式一中的问题,但是其不足之处是,如果获取锁的程序挂掉或者崩溃,锁将永远无法被释放。
方式三:Redisson
为了解决方式二出现的问题,Redisson框架被提出并广泛使用。它是基于Redis的分布式Java数据容器和一种常用的分布式锁解决方案,提供了多种分布式锁实现方法。
Redisson提供了3种分布式锁实现方式:
普通锁(同步锁)
RLock(可重入锁)
RedLock(多重锁)
这种方式可以解决方式二的所有问题,而且还可以方便的获得锁的状态信息,如获得锁的时间、锁的持有者等。
总结
在Redis中,分布式锁的实现方法有三种,其中每种方式都有其优缺点。SETNX和GETSET的组合方式,是一种比较原始的方式,思路简单,易于实现,但是存在程序异常或者时间过长导致锁过期等风险。Redisson框架则提供了多种分布式锁实现方法,使用起来方便,支持可重入锁和多重锁等,是目前比较优秀的分布式锁。