redis工具类
public class RedisUtil {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
/**
* @Description: 加锁
* @Param: jedis
* @Param: lockKey - 锁名
* @Param: requestId - 请求客户端id:可以使用UUID.randomUUID().toString()
* @Param: expireTime
* @Return: boolean
*/
public static boolean getDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
/**
* @Description: 释放锁
* @Param: jedis -Jedis
* @Param: lockKey - 锁名
* @Param: requestId -客户端id
* @Return: boolean
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
final Long RELEASE_SUCCESS = 1L;
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
锁的实现
public class RedisService {
private static final Logger logger = LoggerFactory.getLogger(RabbitMqService.class);
private static final Logger lockLogger = LoggerFactory.getLogger("LOCK_LOG");
@Autowired
RedisProperties redisProperties;
@Autowired
JedisPool jp;
/**
* 初始化Jedis连接池, 取得jedis连接 ;
* @return redis.clients.jedis.JedisPool
*/
public Jedis getJedis(){
try {
// 设置Jedis连接池参数
return jp.getResource();
}catch (Exception e) {
logger.error("初始化Jedis连接池;ERROR", e);
}
return null;
}
/**
* 获取Redis分布式锁
* @param lockKey 锁的关键值
* @return java.lang.String 成功返回请求ID,解锁使用
*/
public String getLocker(String lockKey) {
try {
Jedis jedis = getJedis();
if(null != jedis) {
String reqId = UUID.randomUUID().toString();
//logger.debug("get locker uuid is {}", lockKey);
lockLogger.info("lockKey is {}, requestId is {}", lockKey, reqId);
if (RedisUtil.getDistributedLock(jedis, lockKey, reqId, VideoRing.REDIS_LOCK_EXPIRED)) {
return reqId;
}
} else {
logger.info("redis 连接为空!");
}
} catch(Exception e) {
logger.error("获取Redis分布式锁ERROR", e);
}
return null;
}
/**
* 在默认时间内,完成加锁直到成功为止;
* @param lockKey
* @return java.lang.String 成功返回UUID(requestId);
*/
public String setLockToSuccess(String lockKey) throws InterruptedException {
String res = null;
int i = 0;
do {
logger.info("set locker to Success is {}", "LockKey-" + lockKey);
res = getLocker("LockKey-" + lockKey);
if (null == res) {
sleep(VideoRing.REDIS_LOCK_WAIT);
}
i++;
} while (null == res && i < VideoRing.REDIS_LOCK_NUMS);
if(res == null) {
//记录加锁失败数据到文件中
}
return res;
}
/**
* 释放redis锁
* @param lockKey
* @param requestId
* @return boolean
*/
public boolean releaseLock(String lockKey, String requestId) {
boolean rs = false;
Jedis jedis = getJedis();
try {
if(null != jedis) {
logger.debug("UUID IS {}, 解锁 {}", requestId, "LockKey-" + lockKey);
rs = RedisUtil.releaseDistributedLock(jedis, "LockKey-" + lockKey, requestId);
jedis.close();
} else {
logger.info("redis 不存在!");
}
return rs;
}catch(Exception e) {
logger.error("释放redis锁是出错!", e);
}
return false;
}
}
用到的常量
/*************** redis锁失效时间控制 ***************/
//锁的最大持续时间600秒, 避免死锁;
public static final Integer REDIS_LOCK_EXPIRED = 600;
//持续加锁总次数;
public static final Integer REDIS_LOCK_NUMS = 1500;
//等待下次加锁时间,300ms;
public static final Integer REDIS_LOCK_WAIT = 200;
/*************** redis锁失效时间控制 ***************/