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

Conheça o banco de dados Redis:iterando sobre chaves

Uma das coisas que muitas vezes confunde os usuários que estão familiarizados com outros bancos de dados quando tentam o Redis é a falta de visibilidade no banco de dados:não há um conjunto de tabelas ou coleções para veja, apenas um espaço de chave simples e plano que poderia (potencialmente) ter milhões de chaves. A capacidade de iterar de forma barata nesse espaço de chave torna-se muito importante para se familiarizar com o conteúdo do banco de dados.

A iteração sobre o espaço de chave do Redis tem outros casos de uso importantes, alguns que vêm à mente são:

  • coleta de lixo ou limpeza de chaves que correspondem a um determinado padrão
  • movimentação de dados e alterações de esquema ou movimentação de um determinado conjunto de chaves para outra estrutura de dados
  • depuração, amostragem de dados, correções de dados ou localização e correção de todas as chaves que foram alteradas por uma alteração recente

Neste post, vamos nos aprofundar em várias opções de iteração de espaço-chave disponíveis no Redis.

O(N) Iteradores:CHAVES

O comando Redis KEYS retorna todas as chaves no banco de dados que correspondem a um padrão (ou todas as chaves no espaço de chaves). Comandos semelhantes para buscar todos os campos armazenados em um hash são HGETALL e para todos buscar os membros de um SMEMBERS. As próprias chaves do Redis são armazenadas em um dicionário (também conhecido como tabela de hash). O comando KEYS funciona iterando sobre este dicionário e enviando tudo o que corresponde ao padrão como uma única resposta Array. Os outros comandos funcionam de forma semelhante.

O desempenho de tal operação depende do tamanho da coleção, ou seja, O(N). Assim, o uso de KEYS é severamente desencorajado em ambientes de produção com um grande número de chaves. Redis sendo single threaded, fica bloqueado durante esta iteração, bloqueando assim outras operações. Assim, KEYS deve ser usado apenas para depuração e outras ocasiões especiais em que o desempenho não é uma preocupação (como quando o banco de dados foi colocado offline para aplicar uma correção de dados). A outra coisa importante a ser lembrada sobre esse algoritmo é que ele envia todas as chaves correspondentes juntas como uma única resposta. Isso pode ser extremamente conveniente quando o espaço de chave é pequeno, mas criará vários problemas em um espaço de chave grande. KEYS, no entanto, é um comando favorito entre os desenvolvedores em seus próprios ambientes de desenvolvimento.

CHAVES em ação:

127.0.0.1:6379[1]> MSET um 1 dois 2 três 3 quatro 4OK# Todas as teclas127.0.0.1:6379[1]> teclas *1) "quatro"2) "três"3) " duas"4) "uma"# teclas que começam com a letra 't'127.0.0.1:6379[1]> teclas t*1) "três"2) "duas"# teclas que têm um 'ee' nelas127. 0.0.1:6379[1]> teclas *ee*1) "três"

Iteradores baseados em cursor:SCAN

O SCAN e seus comandos irmãos, SSCAN (para conjuntos), HSCAN (para hashes) e ZSCAN (para conjuntos ordenados) fornecem a abordagem baseada em cursor para iterar sobre estruturas de dados Redis. Eles estão disponíveis no Redis desde a versão 2.8.0.

As chaves são retornadas em iterações incrementais com garantia de tempo constante para cada iteração. Um cursor (um inteiro neste caso) é retornado quando as iterações são inicializadas e um cursor atualizado é retornado a cada iteração. Um ciclo de iteração começa quando o cursor é definido como 0 na solicitação SCAN e termina quando o cursor retornado pelo servidor é 0.  Devido às nuances da arquitetura Redis e da implementação do algoritmo do cursor, aqui estão algumas peculiaridades dessa abordagem:

  • Uma iteração completa sempre recupera todos os elementos que estavam presentes na coleção do início ao fim de uma iteração completa.
  • Uma iteração completa nunca retorna nenhum elemento que NÃO estava presente na coleção do início ao fim de uma iteração completa.
  • Um determinado elemento pode ser retornado várias vezes. Cabe ao aplicativo lidar com o caso de elementos duplicados
  • Elementos que não estavam constantemente presentes na coleção durante uma iteração completa, podem ser retornados ou não:é indefinido.
  • Um número de elementos retornados durante cada contagem varia e pode ser 0 também. No entanto, a iteração não é concluída até que o servidor retorne o valor do cursor 0.
  • O COUNT A opção pode ser usada para limitar o número de elementos retornados em cada iteração. O valor padrão é 10. No entanto, é considerado apenas uma sugestão e não é aplicado em todos os casos. O valor COUNT pode ser alterado durante cada chamada de iteração.
  • A CORRESP A opção permite especificar padrões como o comando KEYS permite.
  • A implementação do cursor é completamente sem estado no lado do servidor. Isso permite que iterações (potencialmente) infinitas comecem em paralelo. Além disso, não há requisitos para garantir que uma iteração continue até o final e possa ser interrompida a qualquer momento.

Apesar de suas peculiaridades, SCAN é um comando muito útil e o comando certo para escolher iterações de espaço-chave para a maioria dos casos de uso.
SCAN é um comando muito útil e o comando certo para escolher iterações de espaço chave em #RedisClick To Tweet

SCAN em ação

127.0.0.1:6379[1]> flushdbOK127.0.0.1:6379[1]> teclas *(lista vazia ou conjunto)127.0.0.1:6379[1]> depurar preencher 33OK127.0.0.1:6379[ 1]> scan 0 COUNT 51) "4"2) 1) "chave:1"   2) "chave:9"   3) "chave:13"   4) "chave:29"   5) "chave:23"127.0. 0.1:6379[1]> scan 4 1) "42"2)  1) "chave:24"    2) "chave:28"    3) "chave:18"    4) "chave:16"    5) "chave:12 "    6) "chave:2"    7) "chave:6"    8) "chave:31"    9) "chave:27"   10) "chave:19"127.0.0.1:6379[1]> scan 421) "9 "2)  1) "chave:3"    2) "chave:4"    3) "chave:20"    4) "chave:8"    5) "chave:32"    6) "chave:5"    7) "chave:26"    8) "key:10"    9) "key:21"   10) "key:14"127.0.0.1:6379[1]> scan 9 COUNT 1001) "0"2) 1) "key:25"   2 ) "chave:30"   3) "chave:22"   4) "chave:17"   5) "chave:15"   6) "chave:0"   7) "chave:11"   8) "chave:7" 

Sob o capô

O algoritmo que SCAN (e seus comandos irmãos) usam para escanear é intrigante e leva a algumas das características do comando que descrevemos acima. Antirez o descreveu em alto nível em seu post no blog e é explicado (um pouco melhor) nos comentários acima da implementação (função dictScan). Descrevê-lo em detalhes tornará este post muito longo, então darei descrição suficiente para tornar suas implicações evidentes.

  • A maioria das estruturas de dados do Redis é representada internamente como dicionários (pelo menos parcialmente no caso de conjuntos classificados). Eles são implementados como tabelas de hash de tamanho de potência de dois com encadeamento para colisões. O desafio de escrever um algoritmo iterativo baseado em cursor aqui é ser capaz de lidar com o crescimento e a redução do hash sem sacrificar os princípios Redis de simplicidade (da API) e velocidade.
  • O SCAN basicamente varre um monte de baldes de hash a cada iteração e retorna os elementos que correspondem ao padrão neles. Como ele analisa apenas uma lista fixa de buckets, algumas iterações de tempo podem não retornar nenhum valor.
  • O cursor que é retornado é basicamente um deslocamento na tabela de hash que está sendo iterada. Ele lida com o crescimento e o encolhimento de tabelas de hash (ou seja, rehashing) pela manipulação inteligente de bits de nível mais alto do deslocamento enquanto aumenta o deslocamento junto com as propriedades da tabela de hash. As implicações dessa abordagem são que novos elementos adicionados durante a iteração podem ou não ser retornados. No entanto, o próprio cursor não precisaria reiniciar em uma alteração no tamanho da tabela de hash.
  • Um determinado bucket deve ser visitado apenas uma vez e todas as suas chaves devem ser retornadas de uma só vez. Isso é novamente para garantir que o redimensionamento de hash (ou seja, rehashing) não complique o progresso da iteração. No entanto, isso faz com que o argumento COUNT não seja estritamente aplicável.
  • Como a abordagem acima é completamente sem estado no lado do servidor, basicamente implica que as iterações podem ser interrompidas ou um grande número de iterações pode ser iniciado em paralelo sem aumentar o uso de memória.

Resumo

Em um nível alto, duas opções estão disponíveis para iterar no espaço de chaves do Redis:

  1. Use KEYS quando o desempenho não for uma preocupação ou quando o espaço da chave tiver um tamanho razoável.
  2. Em todos os outros momentos, use SCAN.
Para iterar no espaço de chave #Redis, use KEYS quando o desempenho não for uma preocupação, caso contrário, use SCANClick To Tweet

Você sabia que agora oferecemos suporte à hospedagem para Redis™*? Obtenha hospedagem totalmente gerenciada para Redis™ na segurança de sua própria conta na nuvem e aproveite os créditos AWS/Azure para suas implantações Redis™.