Bueno, esto se espera de cualquier almacenamiento de datos eficiente: las palabras tienen que ser indexadas en la memoria en una estructura de datos dinámica de celdas vinculadas 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 cual los datos requieren mucha más memoria que un archivo plano correspondiente.
Un conjunto Redis se implementa como una tabla hash. Esto incluye:
- una matriz de punteros creciente geométricamente (potencias de dos)
- puede ser necesaria una segunda matriz cuando rehashing incremental es activo
- celdas de la lista simplemente enlazada que representan las entradas en la tabla hash (3 punteros, 24 bytes por entrada)
- envolturas objeto Redis (uno por valor) (16 bytes por entrada)
- propios datos reales (cada uno de ellos precedido de 8 bytes para el tamaño y capacidad)
Todos los tamaños anteriores se proporcionan para la implementación de 64 bits. Contabilizando la sobrecarga del asignador de memoria, resulta que Redis toma al menos 64 bytes por elemento del conjunto (en la parte superior de los datos) para una versión reciente de Redis usando el asignador jemalloc (> = 2.4)
Redis proporciona memory optimizations para algunos tipos de datos, pero no cubren conjuntos de cadenas. 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 tuviera datos más grandes, esto es lo que puede hacer.
Si no necesita las capacidades de unión, intersección y diferencia de conjuntos, puede almacenar sus palabras en objetos hash. El beneficio es que los objetos hash pueden ser optimizados automáticamente por Redis usando zipmap si son lo suficientemente pequeños. El mecanismo de zipmap ha sido reemplazado por ziplist en Redis> = 2.6, pero la idea es la misma: usar una estructura de datos serializada que pueda caber en las memorias caché de la CPU para obtener tanto un rendimiento como 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 hash.Asumiendo que requiere para almacenar artículos 1 M, añadiendo una palabra podría ser implementado de la siguiente manera:
- hash modulo 10000 (hecho en el lado del cliente)
- palabras HMSET: [hashnum] [palabra] 1
En lugar de almacenar:
words => set{ hi, hello, greetings, howdy, bonjour, salut, ... }
que puede 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 la misma (hash it y use HGET o HEXISTS).
Con esta estrategia, el ahorro de memoria significativa se puede hacer siempre que el módulo de la hash es elige en función de la configuración 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 han cambiado con Redis> = 2.6.
Aquí, el módulo 10000 para elementos de 1M significa 100 elementos por objetos hash, lo que garantizará que todos ellos estén almacenados como zipmaps/ziplists.
respuesta fascinante y detallada; No lo sabía. Gracias @Didier! –
Bien, muchas gracias, estoy bastante seguro de que esto resolverá mis problemas. Y sí para 160mb está bien, pero espero trabajar con hasta 1GB de datos de palabra simple y no quiero que aumente a 10gb. Muchas gracias de nuevo, agradezco la respuesta detallada. – cwoebker
@Didier - ¡Excelente respuesta! Sin embargo, un par de correcciones a) Las entradas Hashtable son una sola lista vinculada, no doble, la sobrecarga de 24 bytes es correcta, aunque b) El contenedor de objetos Redis no se aplica a cada entrada de conjunto/hash. Solo se aplica al par clave/valor de nivel superior, por lo que la sobrecarga es constante c) Es posible que desee indicar que el zipmap está en desuso en 2.6/inestable, y que la lista zip hace lo equivalente. –