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
Redis和Lua实现分布式锁
于 2024-04-02 15:19:12 首次发布