Redis使用场景(二)分布式锁详尽版
分布式锁除了 redis实现外还有:数据库乐观锁和zookeeper效率有限。
分布式锁要满足以下条件:
互斥性:确保同一时刻只有一个客户端持有锁。
不死锁:一个客户端持有锁因断网,崩溃等原因失联了,仍可让下一个人得到锁。
容错性:大部分redis节点可用,客户端就可以加锁解锁。
统一性:加锁和解锁必须为同一客户端。
首先引包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
实现:
public class RedisTool { private static final String LOCK_SUCCESS = "OK"; private static final String SET_NOT_EXIST = "NX"; private static final String SET_EXPIRE_TIME = "PX"; private static final Long RELEASE_SUCCESS = 1L; //加锁 public static boolean addLock(Jedis jedis, String lockKey, String userId, int expireTime) { //参数解析: //1.key 做锁 //2.value:userId 用用户id 来标识锁是谁的 //3.nx xx:两种选择:NX:key不存在才set值 XX:key存在时才set值。 //4.ex px:两种选择:EX:seconds 秒 PX:millSeconds毫秒 //5.设置过期时间 String result = jedis.set(lockKey, userId, SET_NOT_EXIST, SET_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } //解锁 public static boolean goodByeLock(Jedis jedis, String lockKey, String requestId) { //这种写法会出问题 //String result = jedis.get(lockKey); //如果a锁先超时了 这时b获取到了锁,a在解锁时会将b的锁接触 // if (result.equals(requestId)) {// jedis.del(lockKey); // } //这种写法比较正确 String script = "if redis.call('get', KEYS[1]) == args[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; } }

浙公网安备 33010602011771号