使用场景
分布式项目,在高并发的场景下防止资源的超载,例如秒杀超卖问题
利用了Redis的一个特性,多个用户设置同一个Key的value,只能有一个用户设置成功
加锁方法
@Component
public class RedisLock {
@Autowired
private RedisTemplate redisTemplate;
//获取锁
public boolean lock(String key,String value){
//setIfAbsent 设置值,如果设置成功 返回结果 true
if(redisTemplate.opsForValue().setIfAbsent(key,value)){
//设置key的值成功,获取到了锁
return true;
}
//解决死锁问题
//大教室 占了一个位置 放一本书 死锁
//保洁阿姨 固定时间 清理 教室
//给锁设置一个有效期 10秒 过期锁释放掉
//判断当前锁有没有过期
String currentValue = (String) redisTemplate.opsForValue().get(key);
//当前锁的值存储的是一个时间字符串
//判断锁是否过期
if(!StringUtils.isEmpty(currentValue)&&Long.parseLong(currentValue)<System.currentTimeMillis()){
//锁已经过期,重新设置锁的值 getAndSet 先把key对应当前value获取到,设置一个新的value
String oldValue=(String) redisTemplate.opsForValue().getAndSet(key,value);
return !StringUtils.isEmpty(oldValue)&&oldValue.equals(currentValue);
}
return false;
}
}
释放锁的方法(放到同一个类里面)
//解锁
public void unlock(String key,String value){
//获取key对应value的值
try {
String currentValue=(String) redisTemplate.opsForValue().get(key);
//判断当前锁的值不为空,并且当前锁的值和要解锁的值相等,就进行解锁
if(!StringUtils.isEmpty(currentValue)&¤tValue.equals(value)){
//删除key对应数据
redisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("解锁异常");
}
}
使用锁
在使用锁的类里引用锁的对象
@Autowired
private RedisLock redisLock;
在使用锁的类里面加代码
public void Test(){
//设置锁的名称
String appId="creatOrderLock";
//设置锁的值,锁的有效期
//有效期2秒
long timeOut=2*1000L;
String value = (System.currentTimeMillis()+timeOut)+"";
//获取锁
boolean lock = redisLock.lock(appId, value);
if(lock){
/*
这里是被锁的操作
*/
//操作后需要释放锁
//解锁
redisLock.unlock(appId,value);
}
}