redis分布式事务锁:
实现原理:redis通过setNx()方法,setNx()主要的作用就是只能设置同一个key,假如已经存有key,就不能在赋值相同key进入。
避不开的死锁问题:设置失效时间也不能根本解决。
代码实现:
package cn.shop.util;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
@Log4j2
public class RedisLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 加锁
* @param key
* @param value
* @return
*/
public boolean lock(String key,String value){
//setIfAbsent对应redis中的setnx,key存在的话返回false,不存在返回true
if ( stringRedisTemplate.opsForValue().setIfAbsent(key,value)){
return true;
}
//两个问题,Q1超时时间
String currentValue = stringRedisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){
//Q2 在线程超时的时候,多个线程争抢锁的问题
String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){
return true;
}
}
return false;
}
/**
* 解锁
* @param key
* @param value
*/
public void unlock(String key ,String value) {
try {
String currentValue =stringRedisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
log.error("redis分布上锁解锁异常, {}", e);
}
}
}