使用redis做分布式锁
1、使用setnx命令。先看下官方文档http://redis.cn/commands/setnx.html
2、使用getset命令。先获取,再set
实现案例:
* create 2018-12-03 16:22
* <p>
* desc
**/
@Component
@Slf4j
public class RedisLock {
@Autowired
private StringRedisTemplate redisTemplate;
public boolean lock(String key,String timeout){
//在StringRedisTemplate中,setIfAbsent = setnx
//timeout = 当前时间 + 超时时间
if(redisTemplate.opsForValue().setIfAbsent(key,timeout)){
//能成功set则证明拿到了锁
return true;
}
//假如key已经存在
String currentValue = redisTemplate.opsForValue().get(key);//获取当前key的值
/**
* 此处为了防止死锁
*/
//如果锁过期
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){
//获取上一个锁的时间
String oldValue = redisTemplate.opsForValue().getAndSet(key,timeout);
if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
return true;
}
}
return false;
}
//解锁
public void unlock (String key,String value){
String currentValue = redisTemplate.opsForValue().get(key);
try{
if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value)){
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e){
log.error("解锁异常,{}",e);
}
}
}
然后在需要加锁的逻辑上,引用这个锁方法即可
@Autowired
RedisLock redisLock ;
xxxx //业务逻辑
String time = System.currentTimeMillis()+10*1000;//超时10秒钟
if(!redisLock.lock(key,time) ){
//假如没锁上
//抛出异常
}
xxxxx //业务逻辑
//解锁
redisLock.unlock(key,time);
其他方案可参考:
http://www.cnblogs.com/seesun2012/p/9214653.html
----记录学习内容,提高记忆,其中的诸多观点为摘抄总结
------------------------------------业精于勤荒于嬉---------------------------------