setnx+setex:存在设置超时时间失败的情况,导致死锁
set(key,value,nx,px):将setnx+setex变成原子操作
问题:
-
任务超时,锁自动释放,导致并发问题。使用redisson解决(看门狗监听,自动续期)
-
加锁和释放锁不是同一个线程。在value中存入uuid(唯一标识),删除锁时判断该标识(使用lua脚本保证原子操作)
-
不可重入,使用redisson解决(实现机制类似AQS,计数)
-
异步复制可能造成锁丢失,使用redLock解决
lua脚本的示例
--[[
传入参数:
业务标识
ip
限制时间
限制时间内的访问次数
]]--
local busIdentify = tostring(KEYS[1])
local ip = tostring(KEYS[2])
local expireSeconds = tonumber(ARGV[1])
local limitTimes = tonumber(ARGV[2])
local identify = busIdentify .. "_" .. ip
local times = redis.call("GET", identify)
--[[
获取已经记录的时间
获取到继续判断是否超过限制
超过限制返回0
否则加1,返回1
]]--
if times ~= false then
times = tonumber(times)
if times >= limitTimes then
return 0
else
redis.call("INCR", identify)
return 1
end
end
-- 不存在的话,设置为1并设置过期时间
local flag = redis.call("SETEX", identify, expireSeconds, 1)
return 1