2011-09-18 21 views
8

Sto cercando di codificare alcuni dati (in realtà una stringa molto grande) in modo molto efficiente dalla memoria sul lato Redis. Secondo la documentazione Redis, si afferma che "l'uso di hash quando possibile", e dichiara due parametri di configurazione:Ottimizzazione della memoria di Redis

  • I "hash-max-zipmap-voci", che se ho capito bene denota come molte chiavi al massimo devono avere ogni chiave hash (ho ragione?).

  • Il valore "hash-max-zipmap", che indica la lunghezza massima per il valore. Si riferisce al campo o al valore, in realtà? E la lunghezza è in byte, caratteri o cosa?

Il mio pensiero è quello di dividere la stringa (che in qualche modo ha fissato la lunghezza) in quantità tali che giocherà bene con i parametri di cui sopra, e memorizzarli come valori. I campi devono essere numeri di sequenza soli, per garantire una decodifica coerente ..

EDIT: Ho benchmark ampiamente e sembra che codifica la stringa in un hash produce un consumo di memoria ~ 50% in più.

Ecco il mio script di benchmarking:

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 

ed i risultati sulla mia macchina (32bit esempio 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 

chiedo se c'è un modo più efficiente per memorizzare la stringa come un hash, giocando con i parametri che ho citato. Quindi, per prima cosa, devo essere consapevole di cosa significano .. Poi mi occuperò di nuovo e vedrò se c'è più guadagno ..

EDIT2: Sono un idiota? Il benchmarking è corretto, ma è confermato per una grande stringa. Se ripeto per molti grandi archi, immagazzinarli come grandi stringhe è il vincitore definitivo .. Penso che il motivo per cui ho ottenuto quei risultati per una stringa risiede negli interni di Redis ..

+0

Se si sta parlando di un hash crittografico, è impossibile decodificarli, poiché un numero infinito di stringhe diverse viene mappato su un determinato hash. – agf

+0

Hash crittografico? Sto solo cercando di memorizzare una grande stringa in modo efficiente in un hash Redis, dividendola in blocchi di Ai, dove len (Ai) <"hash-max-zipmap-value". Quindi posso ripristinarlo usando chunk_sequence_number, che è il campo che contiene ogni Ai. – hymloth

+0

Non so nulla di Redis, ma "hash" e "decodifica" spesso indicano che qualcuno non capisce come funzionano le funzioni hash. Non so se si applica o meno a questa situazione. – agf

risposta

6

In realtà, il modo più efficiente per archiviare una stringa di grandi dimensioni è una stringa di grandi dimensioni: tutto il resto aggiunge un sovraccarico. Le ottimizzazioni che menzioni sono per gestire un sacco di stringhe brevi, in cui lo spazio vuoto tra le stringhe può diventare un problema.

Le prestazioni per la memorizzazione di una stringa di grandi dimensioni potrebbero non essere buone come per le stringhe piccole a causa della necessità di trovare più blocchi contigui per memorizzarla, ma è improbabile che ciò influisca effettivamente su qualsiasi cosa.

4

Ho provato a leggere i Redis documenti sulle impostazioni che hai citato, e non è facile. Ma non mi sembra che il tuo piano sia una buona idea. L'hashing che descrivono è progettato per risparmiare memoria per valori piccoli. I valori sono ancora memorizzati completamente nella memoria. Mi sembra che stiano riducendo l'overhead quando appaiono molte volte, ad esempio quando una stringa viene aggiunta a molti set. La tua stringa non soddisfa questi criteri. Dubito fortemente che risparmierai la memoria usando il tuo schema.

Ovviamente è possibile confrontarlo per vedere.

1

Prova a guardare l'articolo Redis Memory Usage dove puoi trovare un buon confronto tra vari tipi di dati e il loro consumo di memoria.

Problemi correlati