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

Redis 10x mais uso de memória do que dados


Bem, isso é esperado de qualquer armazenamento de dados eficiente:as palavras têm que ser indexadas na memória em uma estrutura de dados dinâmica de células ligadas por ponteiros. Tamanho dos metadados da estrutura, ponteiros e fragmentação interna do alocador de memória é a razão pela qual os dados ocupam muito mais memória do que um arquivo simples correspondente.

Um conjunto Redis é implementado como uma tabela de hash. Isso inclui:
  • uma matriz de ponteiros crescendo geometricamente (potências de dois)
  • uma segunda matriz pode ser necessária quando o rehashing incremental estiver ativo
  • células de lista vinculada a um único que representam as entradas na tabela de hash (3 ponteiros, 24 bytes por entrada)
  • Envolvedores de objetos Redis (um por valor) (16 bytes por entrada)
  • dados reais (cada um deles prefixado por 8 bytes para tamanho e capacidade)

Todos os tamanhos acima são fornecidos para a implementação de 64 bits. Contabilizando a sobrecarga do alocador de memória, isso resulta no Redis levando pelo menos 64 bytes por item definido (em cima dos dados) para uma versão recente do Redis usando o alocador jemalloc (>=2.4)

O Redis fornece otimizações de memória para alguns tipos de dados, mas não abrange conjuntos de strings. Se você realmente precisa otimizar o consumo de memória dos conjuntos, existem truques que você pode usar. Eu não faria isso por apenas 160 MB de RAM, mas se você tiver dados maiores, aqui está o que você pode fazer.

Se você não precisar dos recursos de união, interseção e diferença de conjuntos, poderá armazenar suas palavras em objetos de hash. O benefício é que os objetos de hash podem ser otimizados automaticamente pelo Redis usando o zipmap se forem pequenos o suficiente. O mecanismo zipmap foi substituído por ziplist no Redis>=2.6, mas a ideia é a mesma:usar uma estrutura de dados serializada que possa caber nos caches da CPU para obter desempenho e um espaço de memória compacto.

Para garantir que os objetos de hash sejam pequenos o suficiente, os dados podem ser distribuídos de acordo com algum mecanismo de hash. Supondo que você precise armazenar 1 milhão de itens, adicionar uma palavra pode ser implementado da seguinte maneira:
  • hash it módulo 10000 (feito no lado do cliente)
  • Palavras HMSET:[hashnum] [palavra] 1

Em vez de armazenar:
words => set{ hi, hello, greetings, howdy, bonjour, salut, ... }

você pode armazenar:
words:H1 => map{ hi:1, greetings:1, bonjour:1, ... }
words:H2 => map{ hello:1, howdy:1, salut:1, ... }
...

Para recuperar ou verificar a existência de uma palavra, é o mesmo (hash e use HGET ou HEXISTS).

Com essa estratégia, uma economia significativa de memória pode ser feita desde que o módulo do hash seja escolhido de acordo com a configuração do zipmap (ou ziplist para Redis>=2.6):
# Hashes are encoded in a special way (much more memory efficient) when they
# have at max a given number of elements, and the biggest element does not
# exceed a given threshold. You can configure this limits with the following
# configuration directives.
hash-max-zipmap-entries 512
hash-max-zipmap-value 64

Cuidado:o nome desses parâmetros foi alterado com Redis>=2.6.

Aqui, módulo 10000 para 1M de itens significa 100 itens por hash objects, o que garantirá que todos eles sejam armazenados como zipmaps/ziplists.