2011-09-18 22 views
8

Estoy tratando de codificar algunos datos (una cadena muy grande en realidad) de una manera muy eficiente con la memoria en el lado de Redis. Según los docs Redis, se afirma que "el uso hashes cuando sea posible", y se declara dos parámetros de configuración:Optimización de la memoria Redis

  • Los "hash max-zipmap-entradas", que si he entendido bien denota cómo muchas teclas como máximo cada tecla hash debe tener (¿estoy en lo cierto?).

  • El "hash-max-zipmap-value", que denota la longitud máxima del valor. ¿Se refiere al campo o al valor, en realidad? Y la longitud es en bytes, caracteres o qué?

Mi idea es dividir la cadena (que de alguna manera ha longitud fija) en cantidades tales que juega bien con los parámetros anteriores, y guardarlas como valores. Los campos deben ser sólo los números de secuencia, para garantizar una decodificación coherente ..

EDITAR: he referenciado ampliamente y parece que codifica la cadena en un hash produce un consumo de memoria ~ 50% mejor.

Aquí es mi guión evaluación comparativa:

import redis, random, sys 

def new_db(): 
    db = redis.Redis(host='localhost', port=6666, db=0) 
    db.flushall() 
    return db 

def db_info(db): 
    return " used memory %s " % db.info()["used_memory_human"] 

def random_string(_len): 
    letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" 
    return "".join([letters[random.randint(0,len(letters)-1)] for i in range(_len) ]) 

def chunk(astr, size): 
    while len(astr) > size: 
     yield astr[:size] 
     astr = astr[size:] 
    if len(astr): 
     yield astr 

def encode_as_dict(astr, size): 
    dod={} 
    cnt = 0 
    for i in chunk(astr,size): 
     dod[cnt] = i 
     cnt+=1 
    return dod 


db=new_db() 
r = random_string(1000000) 
print "size of string in bytes ", sys.getsizeof(r) 
print "default Redis memory consumption", db_info(db) 
dict_chunk = 10000 

print "*"*100 
print "BENCHMARKING \n" 

db=new_db() 
db.set("akey", r) 
print "as string " , db_info(db) 
print "*"*100 

db=new_db() 
db.hmset("akey", encode_as_dict(r,dict_chunk)) 
print "as dict and stored at value" , db_info(db) 
print "*"*100 

y los resultados en mi máquina (32 bits ejemplo Redis):

size of string in bytes 1000024 
default Redis memory consumption used memory 534.52K 
****************************************************************************************** 
BENCHMARKING 

as string used memory 2.98M 
****************************************************************************************** 
as dict and stored at value used memory 1.49M 

estoy preguntando si hay una manera más eficiente para almacenar la cadena como un hash, jugando con los parámetros que mencioné. Entonces, en primer lugar, debo ser consciente de lo que significan. Luego haré un benchmark de nuevo y veré si hay más ganancia ...

EDIT2: ¿Soy un idiota? La evaluación comparativa es correcta, pero está confirmada para una cadena grande. Si repito para muchas cadenas grandes, almacenarlas como cadenas grandes es el ganador definitivo ... Creo que la razón por la que obtuve esos resultados para una cadena yace en las internas de Redis.

+0

Si está hablando de un hash criptográfico, es imposible decodificarlos, ya que un infinito número de cadenas diferentes se asigna a un hash determinado. – agf

+0

hash criptográfico? Solo intento almacenar una cadena grande de manera eficiente en un hash Redis, dividiéndola en fragmentos Ai, donde len (Ai) <"hash-max-zipmap-value". Luego puedo restaurarlo usando chunk_sequence_number, que es el campo que contiene cada Ai. – hymloth

+0

No sé nada sobre Redis, pero "hash" y "decodificación" a menudo significan que alguien no comprende cómo funcionan las funciones hash. No sé si se aplica o no a esta situación. – agf

Respuesta

6

En realidad, la manera más eficiente de almacenar una cadena grande es como una cadena grande; cualquier otra cosa agrega sobrecarga. Las optimizaciones que menciona son para hacer frente a muchas cadenas cortas, donde el espacio vacío entre las cadenas puede convertirse en un problema.

El rendimiento en el almacenamiento de una cadena grande puede no ser tan bueno como para cadenas pequeñas debido a la necesidad de encontrar bloques más contiguos para almacenarlo, pero es poco probable que realmente afecte a algo.

4

He intentado leer la Redis documentación sobre la configuración que menciona, y no es fácil. Pero no me parece que su plan sea una buena idea. El hash que describen está diseñado para ahorrar memoria para valores pequeños. Los valores todavía se almacenan completamente en la memoria. Me parece que están reduciendo los gastos generales cuando aparecen muchas veces, por ejemplo, cuando se agrega una cadena a muchos conjuntos. Su cadena no cumple estos criterios. Dudo mucho que ahorrará memoria utilizando su esquema.

Por supuesto, puede compararlo para ver.

1

Intente ver el artículo Redis Memory Usage donde puede encontrar una buena comparación de varios tipos de datos y su consumo de memoria.

Cuestiones relacionadas