一、Redis加锁流程
加锁步骤:
1、判断Redis锁是否存在;
2、若不存在则加锁,并给锁加上有效期,防止死锁;
正确做法:
public Boolean Lock(String key, String val, long milliSeconds) {
return redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
Jedis jedis = (Jedis) redisConnection.getNativeConnection();
String result = jedis.set(key, val, "NX", "PX", milliSeconds);
if (LOCK_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
});
}
1、第一个参数是key,
2、第二个参数是requestId,确定是哪一个请求加的锁,
3、第三个参数的NX表示 不存在则添加,
4、第四个参数的PX表示 时间单位为毫秒,
5、第五个参数表示有效期时间
错误操作:
public static void wrongGetLock1(Jedis jedis, String lockKey, String requestId, int expireTime) {
Long result = jedis.setnx(lockKey, requestId);
if (result == 1) {
// 若在这里程序突然崩溃,则无法设置过期时间,将发生死锁
jedis.expire(lockKey, expireTime);
}
}
二、Redis解锁流程
解锁流程:
1、判断锁是否存在;
2、判断value是否和requestId相等;
3、删除锁;
正确做法:
private static final Long RELEASE_SUCCESS = 1L;
private static final String RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
public Boolean releaseLock(String key, String val) {
return redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> {
Jedis jedis = (Jedis) redisConnection.getNativeConnection();
Object result = jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(key),
Collections.singletonList(val));
if (RELEASE_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
});
}
错误操作:
public static void wrongReleaseLock(Jedis jedis, String lockKey, String requestId) {
// 判断加锁与解锁是不是同一个客户端
if (requestId.equals(jedis.get(lockKey))) {
// 若在此时,这把锁突然不是这个客户端的,则会误解锁
jedis.del(lockKey);
}
}
Redis客户端链接
https://github.com/Sidfate/RedisCX/releases/download/v0.5.4/RedisCX.Setup.0.5.4.exe