Redis和Lua实现分布式锁

redlock伪码(我看了很多博客,都没有这段代码,下面这个应该就是个伪码,并不是lua脚本):
local key = KEYS[1]
local value = ARGV[1]
local ttl = ARGV[2] 
local lock_num = tonumber(ARGV[3]) 

local retry_delay = 5000 -- 重试等待时间,单位 ms
local max_retry_count = 3 -- 最大重试次数
local quorum = math.ceil(lock_num / 2)
 
math.randomseed(redis.call('TIME')[1])

local total_retry_count = max_retry_count
 
while total_retry_count > 0 do
    local locked_nodes = 0
    local failed_nodes = {}
    for _, instance in ipairs(redis.replicas(name)) do
        local ok = pcall(function ()
            if instance:setnx(key, value) == 1 then
                instance:expire(key, ttl)
                locked_nodes = locked_nodes + 1
            end
         end)
         if not ok then
            table.insert(failed_nodes, instance)
         end
 
         if locked_nodes >= quorum then
            return true
         end
    end
 
   这里我问了gpt,不是只释放failed_nodes,而是释放所有加锁成功的nodes
   for _, node in ipairs(redis.replicas(name)) do
       	if node:get(key) == value then
            node:del(key)
        end
   end
   
    total_retry_count = total_retry_count - 1
 
    if total_retry_count > 0 then
        redis.pcall('sleep', retry_delay / 1000.0)
    end
end
 
return false


加锁和解锁的lua脚本如下:
local result = redis.call('setnx' , KEYS[1] , ARGV[1])
if result == 1 then
    --PEXPIRE:以毫秒的形式指定过期时间
    redis.call('pexpire' , KEYS[1] , 3600000)
else
    result = -1;
    -- 如果value相同,则认为是同一个线程的请求,则认为重入锁
    local value = redis.call('get' , KEYS[1])
    if (value == ARGV[1]) then
        result = 1;
        redis.call('pexpire' , KEYS[1] , 3600000)
    end
end
--  如果获取锁成功,则返回 1

if redis.call('get', KEYS[1]) == ARGV[1]
    then
        return redis.call('del', KEYS[1])
    else
        return 0
end
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成长是自己的事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值