参考
https://blog.csdn.net/sdmxdzb/article/details/78410494
分布式锁的主要实现
- 数据库
- Memcached(add 命令)
- Redis(setnx 命令)
- Zookeeper(临时顺序节点)
Redis 获取分布式锁
jedis.set (String key, String value, String nxxx, String expx, int time)
-
key:使用 key 来代表锁,因为 key 是唯一的
-
value:可以传 requestId,使用 requestId 来标识 是哪一个redis客户端,在释放锁时能作为依据。可以使用 UUID.randomUUID().toString() 方法生成 requestId。
-
nxxx:这个参数可以传 NX,意思是 SET IF NOT EXIST
-
expx:这个参数可以传 PX,表示给这个key加一个过期时间,具体时间由第五个参数(time 参数)给出。
-
time:与第四个参数相呼应,代表key的过期时间。
也可像下文一样 使用 lua脚本 实现
Redis 释放分布式锁
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
第一行代码为一个简单的 Lua脚本 代码,Lua脚本可以保证 原子性。
第二行代码,eval() 方法将 Lua 代码交给Redis执行。将参数KEYS[1] 赋值为 lockKey,ARGV[1] 赋值为 requestId。
首先获取锁对应的 value 值,检查是否与 requestId 相等,如果相等则释放锁。
超时问题
如果 redis 加了锁后,在加锁和释放锁之间的逻辑处理太长,以至于超出了锁的超时时间,将会导致出错