redis分布式锁
直接上代码,我写了四个redis分布式锁的方法,大家可以提个意见:
第一种方法:
/**
* redis分布式锁
* @param timeout
*/
public void lock(long timeout) {
long nano = System.nanoTime();
timeout *= 1000000;
try {
while ((System.nanoTime() - nano) < timeout) {
if (this.setnx(key, LOCKED) == 1) {
System.out.println(“add lock ” + key);
this.expire(key, EXPIRE);
locked = true;
break;
}
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void lock() {
lock(TIME_OUT);
}
public void lock(String key) {
this.key = key;
lock();
}
@Override
public void unlock() {
if (locked) {
System.out.println("release lock");
this.del(key);
}
}
public void unlock(String key) {
this.key = key;
unlock();
}
第二种方法:
/**
* 添加分布式锁
* @param lock
* @return
*/
public boolean acquireLock(String lock) {
//通过SETNX试图获取一个lock
boolean success = false;
Jedis jedis = null;
long value = System.currentTimeMillis() + EXPIRE + 1;
//System.out.println(value);
try {
jedis = getPool();
long acquired = jedis.setnx(lock, String.valueOf(value));
//SETNX成功,则成功获取一个锁
if (acquired == 1) {
success = true;
//SETNX失败,说明锁仍然被其他对象保持,检查其是否已经超时
}else {
long oldValue = Long.valueOf(jedis.get(lock));
//超时
if (oldValue < System.currentTimeMillis()) {
String getValue = jedis.getSet(lock, String.valueOf(value));
// 获取锁成功
if (Long.valueOf(getValue) == oldValue) {
success = true;
// 已被其他进程捷足先登了
}else {
success = false;
}
}
//未超时,则直接返回失败
else {
success = false;
}
}
} catch (Exception e) {
System.out.println("[acquireLock(key:" + new String(lock) + ")] jedis Exception:" + e.getMessage());
returnResource(jedis);
} finally {
// 返还到连接池
returnResource(jedis);
}
return success;
}
//释放锁
public void releaseLock(String lock) {
Jedis jedis = null;
long current = System.currentTimeMillis();
try {
jedis = getPool();
// 避免删除非自己获取得到的锁
if (current < Long.valueOf(jedis.get(lock))) {
jedis.del(lock);
}
} catch (Exception e) {
System.out.println("[releaseLock(key:" + new String(lock) + ")] jedis Exception:" + e.getMessage());
returnResource(jedis);
} finally {
// 返还到连接池
returnResource(jedis);
}
}
第三种方法:
public boolean acquire(String lockKey){
int timeout = TIMEOUTMSECS;
Jedis jedis = null;
try {
jedis = getPool();
while (timeout >= 0) {
long expires = System.currentTimeMillis() + EXPIREMSECS + 1;
String expiresStr = String.valueOf(expires); //锁到期时间
if (jedis.setnx(lockKey, expiresStr) == 1) {
// lock acquired
locked = true;
return true;
}
String currentValueStr = jedis.get(lockKey); //redis里的时间
if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
// lock is expired
String oldValueStr = jedis.getSet(lockKey, expiresStr);
//获取上一个锁到期时间,并设置现在的锁到期时间,
//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
//如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
// lock acquired
locked = true;
return true;
}
}
timeout -= 100;
Thread.sleep(100);
}
} catch (NumberFormatException e) {
e.printStackTrace();
returnResource(jedis);
} catch (InterruptedException e) {
e.printStackTrace();
returnResource(jedis);
} finally {
// 释放redis对象
returnResource(jedis);
}
return false;
}
//释放锁
public void release(String lockKey) {
Jedis jedis = null;
try {
jedis = getPool();
jedis.del(lockKey);
} catch (Exception e) {
System.out.println("[release(key:" + new String(lockKey) + ")] jedis Exception:" + e.getMessage());
returnResource(jedis);
} finally {
// 返还到连接池
returnResource(jedis);
}
}
第四种方法:
/**
* 添加锁
* @param key
* @return
*/
public boolean locked(String key) {
Jedis jedis = null;
long timeout = 0L;
long nano = System.nanoTime();
try {
jedis = getPool();
do {
System.out.println(“lock key: ” + key);
Long i = jedis.setnx(key, key);
if (i == 1) {
jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
//System.out.println(“get lock, key: ” + key + ” , expire in ” + DEFAULT_SINGLE_EXPIRE_TIME + ” seconds.”);
return Boolean.TRUE;
} else { // 存在锁
String desc = jedis.get(key);
//System.out.println(“key: ” + key + ” locked by another business:” + desc);
}
if (timeout == 0) {
break;
}
Thread.sleep(100);
} while ((System.nanoTime() - nano) < TIME_OUT*1000000);
return Boolean.FALSE;
} catch (JedisConnectionException je) {
System.out.println(je.getMessage());
returnResource(jedis);
} catch (Exception e) {
System.out.println(e.getMessage());
returnResource(jedis);
} finally {
returnResource(jedis);
}
return Boolean.FALSE;
}
/**
* 释放锁
* @param key
*/
public void unLocked(String key) {
List keys = new CopyOnWriteArrayList<>();
keys.add(key);
unLocked(keys);
}
/**
* 批量释放锁
* @param lockeys
*/
public void unLocked(List lockeys) {
List keys = new CopyOnWriteArrayList();
keys.addAll(lockeys);
Jedis jedis = null;
try {
jedis = getPool();
jedis.del(keys.toArray(new String[0]));
System.out.println("release lock, keys :" + keys);
} catch (JedisConnectionException je) {
System.out.println(je.getMessage());
returnResource(jedis);
} catch (Exception e) {
System.out.println(e.getMessage());
returnResource(jedis);
} finally {
returnResource(jedis);
}
}
/**
* 批量添加锁
* @param keys
* @return
*/
public boolean locked(List keys) {
Jedis jedis = null;
long timeout = 0L;
try {
List needLocking = new CopyOnWriteArrayList();
List locked = new CopyOnWriteArrayList();
jedis = getPool();
long nano = System.nanoTime();
do {
// 构建pipeline,批量提交
Pipeline pipeline = jedis.pipelined();
for (String key : keys) {
needLocking.add(key);
pipeline.setnx(key, key);
}
System.out.println("lock keys: " + needLocking);
// 提交redis执行计数
List