Redis
 sql >> Database >  >> NoSQL >> Redis

Redis 10 volte più utilizzo della memoria rispetto ai dati

Ebbene questo ci si aspetta da qualsiasi efficiente archiviazione dati:le parole devono essere indicizzate in memoria in una struttura dati dinamica di celle collegate da puntatori. La dimensione dei metadati della struttura, dei puntatori e della frammentazione interna dell'allocatore di memoria è il motivo per cui i dati richiedono molta più memoria di un file flat corrispondente.

Un set Redis viene implementato come tabella hash. Ciò include:

  • una matrice di puntatori che crescono geometricamente (potenze di due)
  • Potrebbe essere necessario un secondo array quando è attivo il rehashing incrementale
  • Celle di elenco a collegamento singolo che rappresentano le voci nella tabella hash (3 puntatori, 24 byte per voce)
  • Wrapper di oggetti Redis (uno per valore) (16 byte per voce)
  • dati effettivi stessi (ciascuno preceduto da 8 byte per dimensione e capacità)

Tutte le dimensioni di cui sopra sono fornite per l'implementazione a 64 bit. Tenendo conto dell'overhead dell'allocatore di memoria, Redis prende almeno 64 byte per elemento impostato (sopra i dati) per una versione recente di Redis utilizzando l'allocatore jemaloc (>=2.4)

Redis fornisce ottimizzazioni della memoria per alcuni tipi di dati, ma non coprono set di stringhe. Se hai davvero bisogno di ottimizzare il consumo di memoria dei set, ci sono però dei trucchi che puoi usare. Non lo farei per soli 160 MB di RAM, ma se dovessi avere dati più grandi, ecco cosa puoi fare.

Se non hai bisogno delle capacità di unione, intersezione e differenza degli insiemi, puoi memorizzare le tue parole in oggetti hash. Il vantaggio è che gli oggetti hash possono essere ottimizzati automaticamente da Redis usando zipmap se sono abbastanza piccoli. Il meccanismo zipmap è stato sostituito da ziplist in Redis>=2.6, ma l'idea è la stessa:utilizzare una struttura di dati serializzata che può adattarsi alle cache della CPU per ottenere prestazioni e un footprint di memoria compatto.

Per garantire che gli oggetti hash siano sufficientemente piccoli, i dati potrebbero essere distribuiti secondo alcuni meccanismi di hash. Supponendo che tu debba archiviare 1 milione di articoli, l'aggiunta di una parola potrebbe essere implementata nel modo seguente:

  • hash it modulo 10000 (fatto sul lato client)
  • Parole HMSET:[hashnum] [parola] 1

Invece di memorizzare:

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

puoi memorizzare:

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

Per recuperare o verificare l'esistenza di una parola, è lo stesso (hash e usa HGET o HEXISTS).

Con questa strategia, è possibile fare un notevole risparmio di memoria a condizione che il modulo dell'hash sia scelto in base alla configurazione zipmap (o ziplist per 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

Attenzione:il nome di questi parametri è cambiato con Redis>=2.6.

Qui, modulo 10000 per 1M di elementi significa 100 elementi per oggetto hash, il che garantirà che tutti siano archiviati come zipmaps/ziplist.