脚本的起因是获取redis的优先级计数器后,需要对当前优先级自增。在多个进程或者分布式下,原子命令无法作到隔离比如
线程A,B,C
- A.get
- B.get
- A.incr
- C.get
- ...
而我想要的是
- A.get
- A.incr
- B.get
- B.incr
- ...
redis multi方案直接毙了,因为我要获取中间的结果集,所以最后选择lua脚本方案,关于lua自行度娘吧
1.解决表的读取排序问题,网上很多方案是table.sort,太烦,反正我的值固定就三个,直接一个数组加表,干就是了。
2.两段循环解决,次数判定问题。(嵌套循环也无所谓O(n2)的复杂度,这么少的次数。。忽略吧)
3.最后返回哪个任先级
local key = "task:async:count"
local prioritySort={"high","normal","low"}
local priority = {
["low"]=1,
["normal"]=3,
["high"]=5,
}
local function setGetPriority(key)
local priorityDefault
local newData = {}
local data = redis.call('hGetAll', key)
if(next(data) == nil) then
priorityDefault = 'high'
else
for i, v in pairs(data) do
if(i % 2 == 1 ) then
newData[v] = tonumber(data[i+1])
end
end
for index, value in pairs(prioritySort) do
if(newData[value]==nil or newData[value] < priority[value]) then
priorityDefault = value
break
end
end
end
if(priorityDefault == nil) then
if(not redis.call('del', key)) then
return false
end
priorityDefault = "high"
end
if(redis.call('hIncrBy', key, priorityDefault, 1)) then
return priorityDefault
else
return false
end
end
return setGetPriority(key)
最后贴个画的草图,草创方案,后期再优化,欢迎指教