sql >> Base de Datos >  >> NoSQL >> Redis

Redis 10 veces más uso de memoria que datos

Bueno, esto se espera de cualquier almacenamiento de datos eficiente:las palabras deben estar indexadas en la memoria en una estructura de datos dinámica de celdas unidas por punteros. El tamaño de los metadatos de la estructura, los punteros y la fragmentación interna del asignador de memoria es la razón por la que los datos ocupan mucha más memoria que un archivo plano correspondiente.

Un conjunto de Redis se implementa como una tabla hash. Esto incluye:

  • una serie de punteros que crecen geométricamente (potencias de dos)
  • es posible que se requiera una segunda matriz cuando la repetición incremental está activa
  • celdas de lista de enlace único que representan las entradas en la tabla hash (3 punteros, 24 bytes por entrada)
  • Contenedores de objetos de Redis (uno por valor) (16 bytes por entrada)
  • datos reales en sí mismos (cada uno de ellos con un prefijo de 8 bytes para el tamaño y la capacidad)

Todos los tamaños anteriores se dan para la implementación de 64 bits. Teniendo en cuenta la sobrecarga del asignador de memoria, Redis toma al menos 64 bytes por elemento del conjunto (además de los datos) para una versión reciente de Redis que usa el asignador jemalloc (>=2.4)

Redis proporciona optimizaciones de memoria para algunos tipos de datos, pero no cubren conjuntos de cadenas. Sin embargo, si realmente necesita optimizar el consumo de memoria de los conjuntos, existen trucos que puede usar. No haría esto por solo 160 MB de RAM, pero si tiene datos más grandes, esto es lo que puede hacer.

Si no necesita las capacidades de unión, intersección y diferencia de los conjuntos, entonces puede almacenar sus palabras en objetos hash. El beneficio es que Redis puede optimizar automáticamente los objetos hash usando zipmap si son lo suficientemente pequeños. El mecanismo zipmap se reemplazó por ziplist en Redis>=2.6, pero la idea es la misma:usar una estructura de datos serializados que pueda caber en las cachés de la CPU para obtener rendimiento y una huella de memoria compacta.

Para garantizar que los objetos hash sean lo suficientemente pequeños, los datos podrían distribuirse de acuerdo con algún mecanismo de hash. Suponiendo que necesita almacenar 1 millón de elementos, agregar una palabra podría implementarse de la siguiente manera:

  • hash it modulo 10000 (realizado en el lado del cliente)
  • Palabras HMSET:[hashnum] [palabra] 1

En lugar de almacenar:

words => set{ hi, hello, greetings, howdy, bonjour, salut, ... }

puedes almacenar:

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

Para recuperar o verificar la existencia de una palabra, es lo mismo (descárguela y use HGET o HEXISTS).

Con esta estrategia, se puede lograr un ahorro significativo de memoria siempre que se elija el módulo del hash de acuerdo con la configuración de zipmap (o 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:el nombre de estos parámetros ha cambiado con Redis>=2.6.

Aquí, módulo 10000 para 1 millón de elementos significa 100 elementos por objetos hash, lo que garantizará que todos ellos se almacenen como zipmaps/ziplists.