/**
* redis分布式锁
* @author Wangkangsheng
*/
@Service
public class RedisLockService implements InitializingBean {
/**
* Key前缀
*/
private static final String PREFIX = "R:LOCK_";
@Autowired
private RedisTemplate<String,String> redisTemplate;
private ValueOperations<String, String> strOper;
/**
* 默认cas次数-1 即不限制次数表
*/
private static final int DEF_REPEAT = -1;
/**
* 默认过期时间 24秒
*/
private static final long DEF_EXPIRE = 24;
/**
* 删除Key的LUA脚本
*/
private static final String LUV_SCRIPT = "if redis.call('get',KEYS[1]) == ARGV[1] then" +
" return redis.call('del',KEYS[1]) " +
" else " +
" return 0 " +
" end";
/**
* 尝试获取锁
* @param key String 锁名称
* @param timeUnit TimeUnit 时间单位
* @param expire long 锁过期时间
* @return boolean 获取锁结果
*/
public synchronized boolean tryLock(String key, TimeUnit timeUnit,long expire){
final String rk = PREFIX+key;
return Boolean.TRUE.equals(strOper.setIfAbsent(rk, rk, expire, timeUnit));
}
/**
* 尝试获取锁 并使用默认的过期时间
* @param key String 锁名称
* @return boolean
*/
public synchronized boolean tryLock(String key){
return tryLock(key,TimeUnit.SECONDS,DEF_EXPIRE);
}
/**
* 获得锁
* @param key String 锁名称
* @param timeUnit TimeUnit 时间单位
* @param expire long 过期时间
* @param casRepeat int cas重复次数
* @return boolean 是否获取锁
*/
public boolean lock(String key, TimeUnit timeUnit,long expire,final int casRepeat){
LongAdder t = new LongAdder();
while (true){
boolean lock = tryLock(key, timeUnit, expire);
if (lock) {
return true;
}else {
if (casRepeat > 0 && t.intValue() > casRepeat){
return false;
}
}
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException ignored) {
}
}
}
/**
* 获取锁 不限制cas次数
* @param key String 锁名称
* @param timeUnit TimeUnit 时间单位
* @param expire long 过期时间
* @return boolean 是否获取锁
*/
public boolean lock(String key, TimeUnit timeUnit,long expire){
return lock(key, timeUnit, expire, DEF_REPEAT);
}
/**
* 获取锁 不限制cas次数并使用默认的过期时间
* @param key String 锁名称
* @return boolean 是否获取锁
*/
public boolean lock(String key){
return lock(key, TimeUnit.SECONDS,DEF_EXPIRE, DEF_REPEAT);
}
/**
* 获得成功后执行代码
* @param key String 锁名称
* @param timeUnit TimeUnit 时间单位
* @param expire long 过期时间
* @param casRepeat int cas重复次数
* @param runnable 获取锁之后执行的代码
*/
public void doOnLock(String key, TimeUnit timeUnit,long expire,final int casRepeat,Runnable runnable){
if (lock(key, timeUnit, expire,casRepeat)) {
try {
runnable.run();
}finally {
boolean b = releaseLock(key);
if (!b) {
releaseLock(key);
}
}
}
}
/**
* 获得成功后执行代码 不限制获取锁cas次数
* @param key String 锁名称
* @param timeUnit TimeUnit 时间单位
* @param expire long 过期时间
* @param runnable 获取锁之后执行的代码
*/
public void doOnLock(String key, TimeUnit timeUnit,long expire,Runnable runnable){
doOnLock(key, timeUnit, expire, DEF_REPEAT,runnable);
}
/**
* 获得成功后执行代码 不限制获取锁cas次数并使用默认的锁过期时间
* @param key String 锁名称
* @param runnable 获取锁之后执行的代码
*/
public void doOnLock(String key,Runnable runnable){
doOnLock(key, TimeUnit.SECONDS,DEF_EXPIRE, DEF_REPEAT,runnable);
}
/**
* 释放锁
* @param key String 锁名称
* @return boolean 释放结果
*/
public synchronized boolean releaseLock(String key){
final String rk = PREFIX+key;
Long execute = redisTemplate.execute(new DefaultRedisScript<>(LUV_SCRIPT,Long.class), Collections.singletonList(rk), rk);
return execute != null && 1 == execute;
}
@Override
public void afterPropertiesSet() throws Exception {
strOper = redisTemplate.opsForValue();
}
}
Redis+RedisTemplate分布式锁
最新推荐文章于 2023-04-21 20:37:04 发布