Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Como excluir atomicamente milhões de chaves correspondentes a um padrão usando Redis puro?


O seguinte script Lua usa SCAN comando, então ele exclui em pedaços dentro do script - evitando o erro "muitos elementos para descompactar".
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

Ele retorna quantas vezes SCAN foi chamado e quantas chaves foram deletadas.

Usar como:
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

Observe que ele bloqueará o servidor durante a execução, portanto, não é recomendado para produção como está.

Para produção, considere alterar DEL para UNLINK . Você também pode retornar o cursor (em vez de repetir dentro do script até que seja zero) e adicionar o parâmetro COUNT para SCAN para estrangular (consulte Existe algum valor recomendado de COUNT para o comando SCAN / HSCAN no REDIS?). Dessa forma, você faz isso em partes em vez de uma única vez, semelhante a Como posso obter todos os conjuntos em redis?

Ou você pode fazer algo mais sofisticado usando a abordagem declarada nesta resposta:Redis `SCAN`:como manter um equilíbrio entre as chaves recém-chegadas que podem corresponder e garantir o resultado final em um tempo razoável?