如何使用纯redis自动删除与模式匹配的数百万个密钥?

r6l8ljro  于 2021-06-09  发布在  Redis
关注(0)|答案(2)|浏览(434)

假设我有数百万 prefix:<numeric_id> 钥匙。
我想用原子方式把它们都清除掉。
如何使用redis自动删除与模式匹配的键显示了许多选项。一些用途 redis-cli 或者bash脚本,但我需要使用我的客户机以编程方式来完成。
lua脚本方法很有前途,但解决方案 KEYS 命令失败,出现“要解包的元素太多”错误。
如何做到这一点?

f2uvfpb9

f2uvfpb91#

下面的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 . 您还可以返回光标(而不是在脚本中重复直到它为零),并将count参数添加到scan to throttle(请参阅redis中是否有任何建议的scan/hscan命令计数值?)。这种方法可以分块而不是一次完成,类似于我如何在redis中获得所有的集合?
或者,您可以使用这个答案中所述的方法做一些更复杂的事情:redis“scan”:如何在可能匹配的键之间保持平衡,并确保在合理的时间内最终得到结果?

cqoc49vn

cqoc49vn2#

lua是一个很好的选择,只要你不使用redis集群或者你想删除的所有密钥都在同一个shard上。
如果您需要从多个shard中删除密钥,您仍然可以使用lua,但是您必须发送 Eval 命令所有碎片“手动”。
另一种方法是使用redisgears(redis模块),它允许您基于某些条件编写跨集群del命令。
参见示例:https://oss.redislabs.com/redisgears/examples.html#delete-按键前缀

相关问题