三种Redis分布式锁实现机制分析(三种redis分布式锁)
Redis是基于内存的数据存储,具有高性能、易安装部署等特点,使用普遍,现在日益深入的应用在分布式系统中,因其原子性和极高的性能,在构建分布式中的锁系统时,Redis是极佳的选择。下面我们就来梳理分析Redis分布式锁的几种实现机制。
1、基于数据加锁机制
具体的实现法是通过setnx(SET IF NOT EXISTS)命令和expire命令来实现,多个客户端通过共享变量来抢夺锁资源,如果该变量未被设置值,则第一个客户端设置变量并产生锁,其他客户端抢夺该变量资源成功的概率将会大大降低,这样便可以实现锁的效果。另外,为了防止客户端在持有锁的过程中出现异常而导致锁无法释放,还可以设置一个锁的有效时间,一旦该有效时间到达,锁便会自动释放掉。
实现代码示例:
# 第一段
KEYS[1] --锁标识名ARGS[1] --请求超时时间
ARGV[1] --当前客户端请求时间
# 第二段local lock = "lock"
if (redis.call("SETNX",KEYS[1],ARGV[1]) == 1) then --判断锁是否被占用 redis.call("expire",KEYS[1],ARGS[1]) --设置锁有效期
return lockelse
if (redis.call("GET",KEYS[1]) redis.call("GETSET",KEYS[1], ARGV[1]) --重置锁的有效期
return lock end
endreturn nil
2、基于Lua脚本加锁机制
与基于数据加锁相比,基于Lua脚本加锁的机制性能要好,因为Lua脚本只需要进行一次传输,而不必按照数据抢锁的步骤进行,而且,由于Lua脚本可以被Redis服务器缓存,从而只需要一次传输后,就可以反复执行,从而大大提升了客户端与Redis服务器的性能。
实现代码示例:
# 第一段
KEYS[1] --锁标识名ARGS[1] --请求超时时间
ARGV[1] --当前客户端请求时间
# 第二段if (redis.call('SETNX', KEYS[1],ARGV[1]) == 1) then --抢夺锁资源
redis.call("Expire",KEYS[1],ARGS[1]) --设置锁的有效时间 return 1 --锁的控制权交给当前客户端
else if (redis.call("get",KEYS[1]) == ARGV[1]) then --判断锁是否属于当前客户端
redis.call("Expire",KEYS[1],ARGS[1]) --刷新锁的有效时间 return 1 --锁仍属于当前客户端
else if (redis.call('get', KEYS[1])
redis.call('getSet', KEYS[1], ARGV[1]) --重新设置锁 return 1 --锁的控制权交给当前客户端
else return 0
end end
end
3、基于RedLock加锁机制
RedLock机制被称为Redis的分布式锁,它是在RedLock算法的基础上研发出来的一种加锁机制,它的优点是:它可以在网络拓扑中多个Redis Server中的一个实例释放锁后,其他Redis Server实例中的锁也都可以被释放。
实现代码示例:
# 第一段
// 配置redis服务器列表private static final List redisList;
# 第二段//计算每个redis服务器中 锁 的key
String[] lockKeys = new String[redisList.size()];String lockName = Thread.currentThread().getName() + "_lock_" + key;
for(int i=0; i lockKeys[i] = lockName + i;
}
//生成锁策略RedLock lockPolicy =