目录
article
Redis Lock
Redis Lock
源码
/**
* @param key redis key, 唯一键
* @param value redis value, 这里是时间戳
* @return
* @desc 加锁 true已锁 false未锁
*/
private boolean lock(String key, String value) {
if(redisTemplate.opsForValue().setIfAbsent(key, value, 5, TimeUnit.MINUTES)) { // 对应setnx命令
//可以成功设置,也就是key不存在
return true;
}
// 判断锁超时 - 防止原来的操作异常,没有运行解锁操作 防止死锁
String currentValue = (String) redisTemplate.opsForValue().get(key);
// 如果锁过期
// currentValue 不为空且小于当前时间
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
// 获取上一个锁的时间value
// 对应getset,如果key存在返回当前key的值,并重新设置新的值
// redis是单线程处理,即使并发存在,这里的getAndSet也是单个执行
// 所以,加上下面的 !StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)
// 就能轻松解决并发问题
String oldValue = (String) redisTemplate.opsForValue().getAndSet(key,value);
if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
}
return false;
}
/**
* @param key redis key, 唯一键
* @param value redis value, 这里是时间戳
* @return
* @desc 释放锁 true已释放 false未释放
*/
private void unlock(String key, String value) {
try {
String currentValue = (String) redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);// 删除key
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}