Redis分布式锁

Foreward

正好有业务场景需要使用分布式锁,读到这篇文章,非常好,做下摘录.

Code

  • RedisKey设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class RedisKey {
/**
* 正则表达式.
*/
public static final String REGEX = "\\{[a-zA-Z0-9]*\\}";
/**
* 全局独自执行任务.
*/
public static final String EXEC_LOCK = "exec:lock";
/**
* 和锁配合使用,每个客户端一个标志.
*/
private static final String OWNER_ID = UUID.randomUUID().toString();
/**
* 获取执行指定任务权限key.
*
* @return
*/
public static String getExecLock(Object... objs) {
return replaceKey(EXEC_LOCK, objs);
}
private static String replaceKey(String key, Object... objs) {
for (Object obj : objs) {
key = key.replaceFirst(REGEX, String.valueOf(obj));
}
return key;
}
public static String getOwnerId() {
return OWNER_ID;
}
}
  • RedisService服务工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Slf4j
public class RedisService {
/**
* Only set the key if it does not already exist.
*/
private static final String SET_IF_NOT_EXIST = "NX";
/**
* Set the specified expire time, in milliseconds.
*/
private static final String SET_WITH_EXPIRE_MILL_TIME = "PX";
/**
* Set the specified expire time, in seconds.
*/
private static final String SET_WITH_EXPIRE_SECOND_TIME = "EX";
private static final String LOCK_SUCCESS = "OK";
private static final Long RELEASE_SUCCESS = 1L;

/**
* 设置分布式锁.(过期时间毫秒)
* @param lockKey 锁的名称.
* @param requestId 持锁人ID.
* @param expireTime 锁的超时时间.
* @return 是否获取锁.
*/
public synchronized boolean tryGetDistributeLock(String lockKey, String requestId, int expireTime) {
log.debug("lock key: {}, ownerId: {}, expire time: {}", lockKey, requestId, expireTime);
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_MILL_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}

/**
* 释放分布式锁.
*
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功.
*/
public synchronized boolean releaseDistributedLock(String lockKey, String requestId) {
log.debug("release lock key: {}, ownerId: {}, expire time: {}", lockKey, requestId);
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));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!
Fork me on GitHub