redis分布式锁适用于分布式系统对同一数据操作,要使用redis锁,需要先了解redis的两个命令操作SETNX和GETSET
1、SETNX key value
将key设置值为value,如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做。SETNX是”SET if Not eXists”的简写
2、GETSET key value
自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。
在Java代码中SETNX命令等于setIfAbsent()方法,GETSET命令等于getAndSet()方法
加锁:
public boolean lock(String key, String value) {//value值为当前时间戳+过期时间
//调用setIfAbsent()方法,成功直接返回true,失败表示已经加锁,往下走
if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
String currentValue = stringRedisTemplate.opsForValue().get(key);//获取value值
//如果redis缓存的value值小于当前时间,说明已经过期了,进入if条件
if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
//调用getAndSet()方法,返回旧值,设置新值
String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
//如果旧值等于当前的值,则重新加锁,返回true
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
}
return false;
}
解锁:
public void unlock(String key, String value) {
String currentVaule = stringRedisTemplate.opsForValue().get(key);
try {
if (!StringUtils.isEmpty(currentVaule) && currentVaule.equals(value)) {
stringRedisTemplate.opsForValue().getOperations().delete(key);//删除缓存
}
} catch (Exception ex) {
log.error(ex.getMessage());
}
}