复制代码
package com.jd.common.core.lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import java.util.Collections;
/**
* <p>Description: 分布式锁RedisLock</p>
* <p>Copyright: Copyright (c)2,024</p>
* <p>Company: tope</p>
* <P>Created Date :2024年02月13日</P>
* @version 1.0
*/
@Component
public class RedisLock {
private final static Logger log = LoggerFactory.getLogger(RedisLock.class);
@Autowired
RedisTemplate redisTemplate;
private StringRedisSerializer argsStringSerializer = new StringRedisSerializer();
private StringRedisSerializer resultStringSerializer = new StringRedisSerializer();
private final String EXEC_RESULT = "1";
//定义获取锁的lua脚本
private final static DefaultRedisScript<String> LOCK_LUA_SCRIPT = new DefaultRedisScript<>(
"if redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2]) then "
+ "return '1' "
+ "else "
+ "return '0' "
+ "end"
, String.class
);
//定义释放锁的lua脚本
private final static DefaultRedisScript<String> UNLOCK_LUA_SCRIPT = new DefaultRedisScript<>(
"if redis.call('get',KEYS[1]) == ARGV[1] then "
+ "return tostring(redis.call('del',KEYS[1])) "
+ "else "
+ "return '0' "
+ "end"
, String.class
);
/**
* 加锁操作
* @param key Redis 锁的 key 值
* @param requestId 请求id,防止解了不该由自己解的锁 (随机生成)
* @param expireTime 锁的超时时间(毫秒)
* @param retryTimes 获取锁的重试次数
* @return true or false
*/
@SuppressWarnings("unchecked")
public boolean lock(String key, String requestId, String expireTime, int retryTimes) {
if (retryTimes <= 0) {
retryTimes = 1;
}
try {
int count = 0;
while (true) {
String result = (String) redisTemplate.execute(LOCK_LUA_SCRIPT, argsStringSerializer, resultStringSerializer,
Collections.singletonList(key), requestId, expireTime);
log.debug("result:{},type:{}", result, result.getClass().getName());
if (EXEC_RESULT.equals(result)) {
log.info("lock---->result:{},requestId:{}", "加锁成功", requestId);
return true;
} else {
count++;
if (retryTimes == count) {
log.warn("has tried {} times , failed to acquire lock for key:{},requestId:{}", count, key, requestId);
return false;
} else {
log.warn("try to acquire lock {} times for key:{},requestId:{}", count, key, requestId);
Thread.sleep(100);
continue;
}
}
}
} catch (InterruptedException e) {
log.error("lock---->result:{},requestId:{}", "加锁异常", requestId);
}
return false;
}
/**
* 解锁操作
* @param key Redis 锁的 key 值
* @param requestId 请求 id, 防止解了不该由自己解的锁 (随机生成)
* @return true or false
*/
@SuppressWarnings("unchecked")
public boolean unLock(String key, String requestId) {
String result = (String) redisTemplate.execute(UNLOCK_LUA_SCRIPT, argsStringSerializer, resultStringSerializer,
Collections.singletonList(key), requestId);
if (EXEC_RESULT.equals(result)) {
log.info("unLock---->result:{},requestId:{}", "解锁成功", requestId);
return true;
}
return false;
}
}