本节基于Redis简单实现了分布式锁
加锁
/**
* 加锁
* @param key
* @param value
* @param expire
* @return
*/
public boolean lock(String key
, String value
, int expire){
Jedis jedis =
jedisPool.getResource()
;
try {
return ConstUtils.
OK.equals(jedis.set(key
, value
, "NX", "PX", expire))
;
}
catch (Exception e){
LOGGER.error(e.getMessage())
;
}
finally {
jedis.close()
;
}
return false;
}
key:每次加锁时生成的全局唯一键
NX:仅在键不存在的情况才能设置成功
PX:表示以毫秒为单位的过期时间
解锁
/**
* 解锁
* @param key
* @param value
* @return
*/
public boolean unlock(String key
, String value){
Jedis jedis =
jedisPool.getResource()
;
try {
return 1 == (Long)jedis.eval(
scriptMap.get(ConstUtils.
DISTRIBUTED_LOCK_LUA)
, 1, key
, value)
;
}
catch (Exception e){
LOGGER.error(e.getMessage())
;
}
finally {
jedis.close()
;
}
return false;
}
如果一个线程获取锁之后,由于某些原因阻塞了并且超过了过期时间,等到这个线程恢复的时候就有可能误删别的线程的锁。因此在释放锁的时候需要先查询key是否是期望的值,然后再删除该键。为了保证两个操作的原子性,可以在lua中实现。
if redis.
call(
"get",KEYS[
1]) ==
ARGV[
1]
then
return redis.
call(
"del",KEYS[
1])
else
return 0
end