/*
* 文件名:RedisLockUtil
* 创建日期: 2019-02-25
* 作者: deekeydai
* Copyright © 2013-2017Juzilicai All Rights Reserverd
*/
package com.juzilicai.framework.cache.redis;
import com.fenqile.redis.JedisProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 基于Redis实现的分布式锁
*
* @author deekeydai 2019-02-25 14:27
**/
public class RedisLockUtil {
private static final Logger log = LoggerFactory.getLogger(RedisLockUtil.class);
/**
* 持锁时间(毫秒),超时自动放锁
*/
private static final long DEFAULT_LOCK_HOLD_TIME = 2000;
/**
* 排队拿锁时间(毫秒),超时返回拿锁失败
*/
private static final long DEFAULT_LOCK_WAIT_TIME = 1000;
/**
* 每次尝试拿锁等待间隔(毫秒)
*/
private static final long DEFAULT_GET_LOCK_GAP = 10;
/**
* 锁的默认value
*/
private static final String DEFAULT_LOCK_KEY_VALUE = "lock_ing";
/**
* 拿锁
*/
public static boolean lock(String lockKey) {
return lockEntity(lockKey, DEFAULT_LOCK_KEY_VALUE, DEFAULT_LOCK_HOLD_TIME, DEFAULT_LOCK_WAIT_TIME);
}
/**
* 拿锁,并指定锁的value
*/
public static boolean lock(String lockKey, String lockValue) {
return lockEntity(lockKey, lockValue, DEFAULT_LOCK_HOLD_TIME, DEFAULT_LOCK_WAIT_TIME);
}
/**
* 拿锁,并指定锁的value,持锁时间
*/
public static boolean lock(String lockKey, String lockValue, long lockTime) {
return lockEntity(lockKey, lockValue, lockTime, DEFAULT_LOCK_WAIT_TIME);
}
/**
* 拿锁,并指定锁的value,持锁时间,等锁时间
*/
public static boolean lock(String lockKey, String lockValue, long lockTime, long waitTime) {
return lockEntity(lockKey, lockValue, lockTime, waitTime);
}
/**
* 释放锁
*/
public static void unlock(String lockKey) {
JedisProxy jedis = JedisProxy.getMasterInstance();
jedis.del(lockKey);
}
/**
* 释放锁(指定value)
*/
public static void unlock(String lockKey, String lockValue) {
JedisProxy jedis = JedisProxy.getMasterInstance();
if (lockValue.equals(jedis.get(lockKey))) {
jedis.del(lockKey);
}
}
/**
* 校验锁的有效性
*/
public static boolean lockCheck(String lockKey, String lockValue) {
JedisProxy jedis = JedisProxy.getMasterInstance();
return lockValue.equals(jedis.get(lockKey));
}
/**
* 拿锁方法(重试)
*
* @param lockKey
* @param lockValue
* @param lockTime 持锁时长(毫秒)
* @param waitTime 等待时长(毫秒)
* @return
*/
private static boolean lockEntity(String lockKey, String lockValue, long lockTime, long waitTime) {
JedisProxy jedis = JedisProxy.getMasterInstance();
long waitedTime = 0L; // 用户等锁时长(毫秒)
while (true) {
String lockFlag = jedis.set(lockKey, lockValue, "NX", "PX", lockTime);
if ("ok".equalsIgnoreCase(lockFlag)) {
log.info("get the lock success, lockKey:{}, lockValue:{}, lockTime:{}", lockKey, lockValue, lockTime);
return true;
}
try {
Thread.sleep(DEFAULT_GET_LOCK_GAP);
} catch (InterruptedException e) {
log.error("interrupt waiting", e);
return false;
}
waitedTime += DEFAULT_GET_LOCK_GAP;
if (waitedTime > waitTime) {
log.info("wating the lock over time, lockKey:{}", lockKey);
return false;
}
}
}
/**
* 拿锁方法(不重试)
*
* @param lockKey
* @param lockValue
* @param lockTime 持锁时长(毫秒)
* @return
*/
public static boolean lockEntity(String lockKey, String lockValue, long lockTime) {
JedisProxy jedis = JedisProxy.getMasterInstance();
String lockFlag = jedis.set(lockKey, lockValue, "NX", "PX", lockTime);
return "ok".equalsIgnoreCase(lockFlag);
}
}