ps:一文解决redis实现分布式锁的7种方案
www.cnblogs.com/wangyingshu…
redis也可以实现锁操作,我们一般使用redis的命令setnx(key,value),key不存在就新增,存在就什么都不做。
同时又多个客户端发起setnx命令的时候,只有一个客户端可以成功,返回1(true),其他客户端则返回0(false)。
获取锁失败
重试
多个线程同时执行:SETNXLOCKXXXX
只有一个可以执行成功
获取到锁
执行业务逻辑
释放锁,执行:DELLOCK
结束
加锁实现:
释放锁实现:
this.redisTemplate.delete("lock");
但是上面的加锁操作容易出现死锁的情况:刚好获取到锁,业务逻辑出现异常导致释放锁操作无法执行,使得锁无法释放,这就是所谓的死锁
解决方法:给锁设置过期时间,自动释放锁
使用set命令设置过期时间 set key value ex 3 nx
PUBLIC VOID CHECKANDLOCK()
1/加锁,获取锁失败重试
TIMEOUT: 3, TIMEUNIT.SECONDS))
WHILE (!THIS.REDISTEMPLATE.OPSEORVALUE().SETIFABSENT( KEY:"LOCK",
VALUE:
XXXX
TRY
最终还是不能保证原子性操作
最终解决方案
加锁,获取锁失败重试
UUID.RANDOMUUID().TOSTRING();
STRING UUID
(!THIS.REDISTEMPLATE.OPSFORVALUEO.SETIFABSENT("LOCK", UUID,3,
WHILE
TIMEUNIT.SECONDS))(
//释放锁
"IF
STRING SCRIPT
THEN RETURN
11('GET',
KEYS[1]) - ARGV[1]
REDIS.CALL
REDIS.CALL('DEL', KEYS[1]) ELSE
END";
0
RETURN
THIS.REDISTEMPLATE.EXECUTE(NEW DEFAULTREDISSCRIPT<(SCRIPT,
LONG.CLASS), ARRAYS.ASLIST("LOCK"), UUID);