使用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


posted @ 2018-12-03 16:58  SayAndDo  阅读(379)  评论(0编辑  收藏  举报