低版本RedisTemplate
@Configuration
@ConditionalOnBean(RedisTemplate.class)
@Slf4j
public class RedisLockUtil {
private static final Long SUCCESS = 1L;
@Autowired
private RedisTemplate redisTemplate;
/**
* 加锁
* @param lockKey 锁的key
* @param value 锁的val
* @param expireTime 超时时间(秒)
* @return
*/
public boolean Lock(String lockKey, String value, int expireTime) {
try {
String script = "if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end end";
RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value, String.valueOf(expireTime));
if (SUCCESS.equals(result)) {
return true;
}
} catch (Exception e) {
log.error("分布式锁加锁失败", e);
}
return false;
}
/**
* 解锁
* @param lockKey
* @param value
* @return
*/
public boolean unLock(String lockKey, String value) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
if (SUCCESS.equals(result)) {
return true;
}
return false;
}
}
高版本RedisTemplate
高版本中已封装了setIfAbsent(key, val, expreTime, unit)方法,可直接调用
@Configuration
public class RedisLock {
private static final Long SUCCESS = 1L;
@Autowired
private RedisTemplate redisTemplate;
/**
* 加锁
* @param key 锁的key
* @param val 锁的val
* @param timeOut 获取锁的超时时间
* @param expreTime 锁过期时间
* @param unit 过期单位
* @return
*/
public boolean tryLock(String key, String val, long timeOut,long expreTime,TimeUnit unit){
long start = System.currentTimeMillis();
for (;;) {
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(key, val, expreTime, unit);
if (aBoolean){
return true;
}
long time = System.currentTimeMillis() - start;
if (time > timeOut){
return false;
}
}
}
/**
* 解锁
* @param key
* @param val
* @return
*/
public boolean unLock(String key, String val){
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
Object execute = redisTemplate.execute(redisScript, Collections.singletonList(key), val);
if(SUCCESS.equals(execute)) {
return true;
}
return false;
}
}