gpt4 book ai didi

lua - Redis 优化 ZRANGEBYSCORE 所花费的时间

转载 作者:IT王子 更新时间:2023-10-29 06:01:06 25 4
gpt4 key购买 nike

我有一个使用 redis 排序集的队列系统。我的 lua 脚本看起来像:

local moveElement = function(source, dest , score, destscore)
local element = redis.pcall('ZRANGEBYSCORE', source, '-inf',score, 'WITHSCORES' , 'LIMIT' , '0' , '1')
if element ~= false and #element ~= 0 then
redis.call('ZADD' , dest , destscore , element[1])
redis.call('ZREM' , source , element[1])
end
end
local temp = moveElement(KEYS[2], KEYS[1] , ARGV[2])
local temp = moveElement(KEYS[3], KEYS[1] , ARGV[2])
local score= redis.call('ZRANGEBYSCORE', KEYS[1], '-inf',ARGV[1], 'WITHSCORES' , 'LIMIT' , '0' , '10')
if score ~= false and #score ~= 0 then
local i = 1
while i<=#score do
redis.call('ZREM', KEYS[1] , score[i])
redis.call('ZREM', KEYS[2] , score[i])
redis.call('ZADD', KEYS[3], ARGV[1] , score[i])
i=i+2
end
end
return score

这个 lua 脚本需要 24 秒,排序集中有 6K 个成员。

SLOWLOG GET 10

1) 1) (integer) 5937
2) (integer) 1385993558
3) (integer) 24446
4) 1) "EVAL"
2) "local moveElement = function(source, dest , score, destscore) local element = redis.pcall('ZRANGEBYSCORE', sourc... (937 more bytes)"

我的代码方法是:

我使用以下参数调用此脚本。

    1. [键数]
  1. foo1 排序集名称有 6k。
  2. foo2 排序集名称。
  3. foo3 有序集合。从 foo1 到 foo2 的成员被移动到哪里。
  4. 当前时间戳。
  5. 当前时间戳 - 6 分钟。

有没有办法优化所用时间?通过缓存 lau 脚本什么的?

因为我总是从低到高获取值(value),是否可以使用 ZRANGE 帮助代替 ZRANGEBYSCORE?

更多详情:

我正在尝试实现某种类型的队列系统。逻辑在这里:

  1. foo1 包含以分数作为时间戳的成员,在该时间他们需要被解雇。
  2. 每当将来需要触发事件时。它被放在 foo1 中, foo1 有 score 作为调度时间。
  3. 我的脚本从 foo1 读取所有得分小于或等于当前时间戳的成员(一个接一个),并将它们移动到 foo3。这是一个一个完成的,元素被移动。此元素已分配给某个 worker 。 (隐藏)
  4. 如果 worker 完成了工作。它从 foo3 中删除成员。
  5. 如果成员没有删除 foo3,则超时 x 秒后。脚本将其移回 foo1。所以它可以重新分配给其他一些 worker 。

最佳答案

您发布的脚本有一些问题。这是在 Lua 中(请不要发布带引号的字符串,这会使代码难以阅读):

local moveElement = function(source, dest , score, destscore)
local element = redis.pcall(
'ZRANGEBYSCORE', source, '-inf', score, 'WITHSCORES' , 'LIMIT' , '0' , '1'
)
if element ~= false and #element ~= 0 then
redis.call('ZADD' , dest , destscore , element[1] )
redis.call('ZREM' , source , element[1])
end
end

local temp = moveElement(KEYS[2], KEYS[1] , ARGV[2])
local temp = moveElement(KEYS[3], KEYS[1] , ARGV[2])
local score= redis.call(
'ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'WITHSCORES' , 'LIMIT' , '0' , '10'
)
if score ~= false and #score ~= 0 then
local i = 1
while i<=#score do
redis.call('ZREM', KEYS[1] , score[i])
redis.call('ZREM', KEYS[2] , score[i])
redis.call('ZADD', KEYS[3], ARGV[1] , score[i])
i=i+2
end
end
return score

首先,第 5 行,元素永远不会为 false。我怀疑您正在 try catch 错误,但在这种情况下,它将是一个带有 err 字段的表。 score 也一样。

然后,您分配了两个本地 temp 变量,以后不再使用它们。

您的 while 循环最好用 for 编写:

for i=1,#score,2 do
redis.call('ZREM', KEYS[1] , score[i])
redis.call('ZREM', KEYS[2] , score[i])
redis.call('ZADD', KEYS[3], ARGV[1] , score[i])
end

为什么要在 moveElement 中使用 WITHSCORES?你不使用它。

除此之外,您能否更清楚地说明您想要实现的目标,以便我进一步帮助您?无论如何,像这样的操作肯定不会花费 24 秒(除非你在一台古董机器上运行)。

编辑

考虑到您到目前为止告诉我的内容,这是一个更简单的脚本版本:

local now = ARGV[1]
local timed_out = ARGV[2]
local pending_jobs = KEYS[1]
local running_jobs = KEYS[2]
local jobs

local not_empty = function(x)
return (type(x) == "table") and (not x.err) and (#x ~= 0)
end

-- check if some jobs have timed out
-- if yes, take the oldest one and queue it again
jobs = redis.pcall(
'ZRANGEBYSCORE', timed_out, '-inf', timed_out, 'LIMIT', '0', '1'
)
if not_empty(jobs) then
redis.call('ZADD', pending_jobs, now, jobs[1])
redis.call('ZREM', running_jobs, jobs[1])
end

-- check if there are jobs ready
-- if yes, take the 10 oldest ones and run them
jobs = redis.pcall(
'ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'LIMIT', '0', '10'
)
if not_empty(jobs) then
for i=1,#jobs do
redis.call('ZREM', pending_jobs, jobs[i])
redis.call('ZADD', running_jobs, now, jobs[i])
end
end

return jobs

看看这个脚本,我完全看不出为什么它会花费 24 秒之多。所以要么:

  • 您的 Redis 设置有问题,或者
  • 你并没有真正这样做,或者
  • 你的测量有误。

除非您能提供一个包含显示此问题的数据的 .rdb,否则我无话可说...

关于lua - Redis 优化 ZRANGEBYSCORE 所花费的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20330443/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com