使用redis做分散式鎖
阿新 • • 發佈:2018-12-03
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);