redis实现分布式锁

87 阅读1分钟

ps:一文解决redis实现分布式锁的7种方案
www.cnblogs.com/wangyingshu…
redis也可以实现锁操作,我们一般使用redis的命令setnx(key,value),key不存在就新增,存在就什么都不做。
同时又多个客户端发起setnx命令的时候,只有一个客户端可以成功,返回1(true),其他客户端则返回0(false)。

获取锁失败

重试

多个线程同时执行:SETNXLOCKXXXX

只有一个可以执行成功

获取到锁

执行业务逻辑

释放锁,执行:DELLOCK

结束

image.png

加锁实现:

image.png

释放锁实现:
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

image.png

最终还是不能保证原子性操作
最终解决方案

加锁,获取锁失败重试

UUID.RANDOMUUID().TOSTRING();

STRING UUID

(!THIS.REDISTEMPLATE.OPSFORVALUEO.SETIFABSENT("LOCK", UUID,3,

WHILE

TIMEUNIT.SECONDS))(

image.png

//释放锁

"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);

image.png