redis-实现分布式锁
为什么要实现redis分布式锁
redis在高并发环境下,大量请求线程并发get 或者set redis中的缓存数据可能出现数据不一致性问题
一、如何实现?
1.setnx(set if not exists)指令
代码如下(示例):
127.0.0.1:6379> setnx lock testlock
(integer) 1
127.0.0.1:6379>
(integer) 1说明抢占锁成功
再次尝试抢占
127.0.0.1:6379> setnx lock testlock
(integer) 0
(integer) 0说明抢占锁失败
二、如何释放锁?
代码如下(示例):
1.del指令
127.0.0.1:6379> setnx lock testlock
(integer) 1
127.0.0.1:6379> setnx lock testlock
(integer) 0
127.0.0.1:6379> del lock testlock
(integer) 1
127.0.0.1:6379> setnx lock testlock
(integer) 1
127.0.0.1:6379>
二、死锁问题
如果程序运行期间,在del指令之前报错,del指令未执行,这个锁就永久无法释放,造成死锁,如何解决呢?我们在锁上加一个失效时间
127.0.0.1:6379> setnx locktest true
(integer) 1
127.0.0.1:6379> expire locktest 10
(integer) 1
127.0.0.1:6379> setnx locktest true
(integer) 0
127.0.0.1:6379> setnx locktest true
(integer) 0
127.0.0.1:6379> setnx locktest true
(integer) 1
127.0.0.1:6379>
这里还存在一个问题,如果程序运行过程中 要执行expire 的时候,程序失败了,没有加上锁的失效时间,这又会导致锁资源无法释放。
三、彻底死锁问题
要解决第二点的问题 就要使用redis后面加入的一个原子性的分布式锁指令
127.0.0.1:6379> set testlock 1111 ex 20 nx
OK
127.0.0.1:6379> setnx testlock 123
(integer) 0
127.0.0.1:6379> setnx testlock asdasdasd
(integer) 0
127.0.0.1:6379> setnx testlock asdasdasd
(integer) 1