目录
关于排它锁
已在 Redis指令详解-string val相关指令 文章中讲述。
代码封装
/**
* 排它锁
*
* @param randomForLock
* @return
*/
public boolean getNXLock(String key, String randomForLock, long expireSeconds) {
String value = randomForLock;
return (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection -> {
RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
RedisSerializer keySerializer = redisTemplate.getKeySerializer();
Object obj = connection.execute("set", keySerializer.serialize(key),
valueSerializer.serialize(value),
bytes4NX,
bytes4EX,
Long.valueOf(expireSeconds).toString().getBytes());
return obj != null;
});
}
final byte[] bytes4NX = "NX".getBytes();
final byte[] bytes4EX = "EX".getBytes();
final String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end";
/**
* 释放任务排它锁
*
* @param randomForLock
*/
public void releaseNXLock(String key, String randomForLock) {
List<String> keys = Arrays.asList(key);
// 这里returnType的选择,需结合实际与org.springframework.data.redis.connection.ReturnType
RedisScript redisScript = RedisScript.of(script, Long.class);
redisTemplate.execute(redisScript, keys, randomForLock);
}
注意:java Class选择ReturnType的代码,否则会出现 java.lang.IllegalStateException异常。
/**
* Represents a data type returned from Redis, currently used to denote the expected return type of Redis scripting
* commands
*
* @author Jennifer Hickey
* @author Christoph Strobl
*/
public enum ReturnType {
/**
* Returned as Boolean
*/
BOOLEAN,
/**
* Returned as {@link Long}
*/
INTEGER,
/**
* Returned as {@link List<Object>}
*/
MULTI,
/**
* Returned as {@literal byte[]}
*/
STATUS,
/**
* Returned as {@literal byte[]}
*/
VALUE;
/**
* @param javaType can be {@literal null} which translates to {@link ReturnType#STATUS}.
* @return never {@literal null}.
*/
public static ReturnType fromJavaType(@Nullable Class<?> javaType) {
if (javaType == null) {
return ReturnType.STATUS;
}
if (javaType.isAssignableFrom(List.class)) {
return ReturnType.MULTI;
}
if (javaType.isAssignableFrom(Boolean.class)) {
return ReturnType.BOOLEAN;
}
if (javaType.isAssignableFrom(Long.class)) {
return ReturnType.INTEGER;
}
return ReturnType.VALUE;
}
}