Redis 分布式锁 - Lua

Redis 分布式锁 - Lua

基于Lua脚本的分布式锁实现方案,这里列举加锁和释放锁的过程

为什么要用Lua

Redis 在 2.6 版本中推出了脚本功能,允许开发者将 Lua 语言编写的脚本传到 Redis 中执行。使用 Lua 脚本的优点有如下几点:

  1. 减少网络开销:本来需要多次请求的操作,可以一次请求完成,从而节约网络开销;

  2. 原子操作:Redis 会将整个脚本作为一个整体执行,中间不会执行其它命令;

  3. 复用:客户端发送的脚本会存储在 Redis 中,从而实现脚本的复用。

Lua脚本

加锁(可重入锁)

-- 加锁脚本
-- key1:要加锁的名称 argv1:当前线程或主机的地址 argv2:锁存活的时间ms 
local expire_time = tonumber(ARGV[2])
if redis.call('exists', KEYS[1]) == 0 then
   -- 锁不存在,创建一把锁,存入hash类型的值
   redis.call('hset', KEYS[1], ARGV[1], 1)
   -- 设置锁的存活时间,防止死锁
   redis.call('pexpire', KEYS[1], expire_time)
   return 1
end
if redis.call('hexists', KEYS[1], ARGV[1]) == 1 then
   -- 表示是同一线程重入
   redis.call('hincrby', KEYS[1], ARGV[1], 1)
   -- 重新设置锁的过期时间
   redis.call('pexpire', KEYS[1], expire_time)
   return 1
end
-- 没抢到锁,返回失败
return 0

释放锁

-- 解锁脚本
-- 判断是当前线程持有锁,避免解了其他线程加的锁
if redis.call('hexists',KEYS[1],ARGV[1]) == 1 then
   -- 重入次数大于1,扣减次数
   --if tonumber(redis.call('hget',KEYS[1],ARGV[1])) > 1 then
   --    return redis.call('hincrby', KEYS[1], ARGV[1], -1)
   -- 重入次数等于1,删除该锁
   --else
       redis.call('del', KEYS[1]);
       return 1
   --end
-- 判断不是当前线程持有锁,返回解锁失败
else
   return 0
end

本文由 在码圈 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站部分内容收集于互联网,如果有侵权内容、不妥之处,请联系我们删除。敬请谅解!
原文链接:https://www.arcinbj.com/archives/redislock
最后更新于:2020-10-19 20:25:14

请博主喝咖啡 ☕.