Как атомарно удалить миллионы ключей, соответствующих шаблону, используя чистый Redis? - PullRequest
2 голосов
/ 22 апреля 2020

Скажем, у меня есть миллионы prefix:<numeric_id> ключей.

Я хочу очистить их все атомарно.

Как атомарно удалить ключи, соответствующие шаблону, используя Redis показывает много вариантов. Некоторые используют скрипт redis-cli или Bash, но мне нужно сделать это, используя мой клиент, программно.

Подход со сценарием Lua является многообещающим, но решения с командой KEYS завершаются неудачно с ошибкой "слишком много элементов для распаковки".

Как этого добиться?

Ответы [ 2 ]

1 голос
/ 22 апреля 2020

Следующий скрипт 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`: как сохранить баланс между новыми ключами, которые могут совпадать, и обеспечить конечный результат в разумные сроки?

0 голосов
/ 23 апреля 2020

Lua - отличный вариант, если вы не используете Redis Cluster или все ключи, которые вы хотите удалить, находятся на одном и том же осколке.

Если вам нужно удалить ключи из нескольких осколков, можно по-прежнему использовать Lua, но вам придется отправлять команду Eval всем шардам «вручную».

Альтернативой, которая делает это за вас, является использование RedisGears ( модуль Redis), который позволяет вам написать команду кросс-кластера del на основе некоторых критериев.

См. Пример: https://oss.redislabs.com/redisgears/examples.html#delete -by-key-prefix

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...