如何使用纯 Valkey/Redis 自动删除数百万个与模式匹配的键?

问题描述 投票:0回答:2

假设我有数百万个

prefix:<numeric_id>
键。

我想原子地清除它们。

如何使用 Redis 以原子方式删除与模式匹配的键显示了许多选项。有些使用

redis-cli
或 Bash 脚本,但我需要使用我的客户端以编程方式执行此操作。

Lua 脚本方法很有前途,但使用

KEYS
命令的解决方案会失败,并出现“太多元素无法解压”错误。

如何实现这一目标?

redis lua valkey
2个回答
9
投票

以下 Lua 脚本使用

SCAN
命令,因此它会在脚本内分块删除 - 避免“太多元素无法解压”错误。

local cursor = 0
local calls = 0
local dels = 0
repeat
    local result = redis.call('SCAN', cursor, 'MATCH', ARGV[1])
    calls = calls + 1
    for _,key in ipairs(result[2]) do
        redis.call('DEL', key)
        dels = dels + 1
    end
    cursor = tonumber(result[1])
until cursor == 0
return "Calls " .. calls .. " Dels " .. dels

它返回

SCAN
被调用了多少次以及删除了多少个键。

用作:

EVAL "local cursor = 0 local calls = 0 local dels = 0 repeat    local result = redis.call('SCAN', cursor, 'MATCH', ARGV[1])     calls = calls + 1   for _,key in ipairs(result[2]) do       redis.call('DEL', key)      dels = dels + 1     end     cursor = tonumber(result[1]) until cursor == 0 return 'Calls ' .. calls .. ' Dels ' .. dels" 0 prefix:1

请注意,它在运行时会阻塞服务器,因此不建议按原样用于生产。

对于生产,请考虑将

DEL
更改为
UNLINK
。您还可以返回光标(而不是在脚本内重复直到为零)并向 SCAN 添加 COUNT 参数以进行限制(请参阅REDIS 中的 SCAN / HSCAN 命令是否有推荐的 COUNT 值?)。这样你就可以分块完成,而不是一次完成,类似于如何获取redis中的所有集合?

或者您可以使用此答案中所述的方法做一些更复杂的事情:Redis`SCAN`:如何在可能匹配的新通信密钥之间保持平衡并确保在合理的时间内获得最终结果?


1
投票

只要您不使用 Redis 集群或者您要删除的所有键都在同一个分片上,Lua 就是一个不错的选择。

如果您需要从多分片中删除密钥,您仍然可以使用 Lua,但您必须“手动”向所有分片发送

Eval
命令。

为您完成此操作的另一种选择是使用 RedisGears(Redis 模块),它允许您根据某些条件编写跨集群 del 命令。

参见示例:https://oss.redislabs.com/redisgears/examples.html#delete-by-key-prefix

© www.soinside.com 2019 - 2024. All rights reserved.