Следующий скрипт 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
Возвращает сколько раз * Было вызвано 1005 * и сколько ключей было удалено.
Использовать как:
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 для газа (см. Есть ли рекомендуемое значение COUNT для команды SCAN / HSCAN в REDIS? ) , Таким образом, вы делаете это порциями вместо одного go, аналогично Как я могу получить все наборы в Redis?
Или вы можете сделать что-то более сложное, используя заявленный подход в этом ответе: Redis `SCAN`: как сохранить баланс между новыми ключами, которые могут совпадать, и обеспечить конечный результат в разумные сроки?