直接贴上代码
/**
* @param subKey set Key name
* @param timeout get lock timeout,if not get,
* @param unit time unit
* @param sValue
* @return
*/
public static boolean tryLock(String subKey, String sValue,long timeout, TimeUnit unit) {
String key = subKey;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis == null) {
return Boolean.FALSE;
}
long nano = System.nanoTime();
do {
logger.debug("try lock key: " + key);
Long i = jedis.setnx(key, sValue); //此处可能出现死锁(执行setnx后,redis crash ,key一直存在)
if (i == 1) {
jedis.expire(key, 5);//锁失效时间5秒
logger.debug("get lock, key: " + key + " , expire in "
+ 2 + " seconds.");
return Boolean.TRUE;
}
//解决出现死锁问题 可优化为 getset方式 重新设置值
// key存在, 获取key的内容值, 值为nanotime 纳秒 ,当前的时间 - key的值>锁 锁定时间,此时可获取锁
String value = jedis.get(key);
if (StringUtils.isNotBlank(value) &&
!"nil".equalsIgnoreCase(value)&&
(System.nanoTime()-Long.valueOf(value))>TimeUnit.SECONDS.toNanos(5)) {
set(key, value, 5); //设置key 5秒过期 自动释放
return Boolean.TRUE;
}
if (timeout == 0) { // 取不到锁时,不等待,直接返回.
break;
}
Thread.sleep((int)(50*Math.random()+50));// 等待50- 100毫秒 避免不同线程竞争时间相同
} while ((System.nanoTime() - nano) < unit.toNanos(timeout));// 取不到锁时等待,直到timeout
if (logger.isInfoEnabled()) {
String desc = jedis.get(key);
logger.debug("key: " + key
+ " locked by another business:" + desc);
}
return Boolean.FALSE;
}catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
returnResource(jedis);//释放连接
}
return Boolean.FALSE;
}
/** 获取key对应值,对比值内容, 相同则删除,释放锁,避免删除其他线程已经获取的锁
* @param subKey
* @param sValue
*/
public static boolean unLock(String subKey,String sValue) {
String key = subKey;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis == null) {
return false;
}
String str = jedis.get(subKey);
if (str.equals(sValue)) {
jedis.del(key);
logger.debug("release lock, keys :" + key);
return true;
}else {
logger.debug("the key is not exist,key : " + key);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
returnResource(jedis);//释放连接
}
return false;
}
public static void main(String args[]){
String sValue = String.valueOf(System.nanoTime());
String subKey = "productId";
try {
// 5000毫秒
boolean lock = tryLock(subKey, sValue, 5000, TimeUnit.MILLISECONDS);
if (lock) {
//do job 相关业务逻辑
}
} catch (Exception e) {
e.printStackTrace();
}finally{
unLock(subKey, sValue);
}
}