In breve. In Redis scegliere la struttura dati vuol dire scegliere tre cose insieme: quanta memoria paghi, quale operazione costa un solo comando e quale ti costringe a portare i dati nel client. Le misure sono dell'8 novembre 2026, su Redis 8.0.5 e 7.4.7. Un hash di quattro campi occupa 136 byte finché resta piccolo e 336 se lo costringi alla rappresentazione grande. Contare 100.000 visitatori unici con un HyperLogLog costa 14.392 byte contro i 4.772.976 di un Set, e sbaglia dello 0,425%. Una classifica di 100.000 giocatori in un Sorted Set pesa 9,58 MB, ma MEMORY USAGE da solo te ne dice fra 9,0 e 11,0 a seconda dell'istanza: su una struttura annidata campiona cinque elementi e moltiplica, e il conteggio esatto arriva solo con SAMPLES 0. E il caso reale del mio backend, un hash per articolo con un vettore di 1.536 byte, non è mai piccolo: supera il limite dei 64 byte e vive nella rappresentazione larga.
Metodo. Ogni blocco di codice qui sotto è stato eseguito davvero, con la versione scritta accanto: Redis 8.0.5 nativo su istanze usa-e-getta (porta 6391) e Redis 7.4.7 in contenitore. Nella sezione sul campionamento entrano anche le immagini ufficiali 7.4.9, 7.4.12 e 8.10.3, nominate dove servono. Le uniche letture sull'istanza di sviluppo del sito sono marcate come tali. La configurazione di produzione non la conosco e non la dichiaro.
Revisione del 13 novembre 2026. In questa revisione non ho avviato nessun server: le uscite dei blocchi sono quelle dell'8 novembre e non le ho riprodotte. Ho ricontrollato ciò che si verifica senza un server. Le pagine della documentazione ufficiale dicono ancora le stesse cose (la versione corrente del progetto è la 8.10.3, secondo l'elenco delle release). Due calcoli miei tornano: i registri dell'HyperLogLog sono 16.384 da 6 bit, cioè 12.288 byte, con errore standard 1,04/√16.384 = 0,81%; la distanza Roma-Milano con la formula di haversine dà 477,02 km, contro i 477,0191 di Redis, che arrotonda le coordinate nel geohash.
Il problema: una chiave sola non basta a capire cosa stai pagando
Quando in un backend arriva Redis, la prima domanda è quasi sempre «che chiave uso?». La domanda utile viene un passo dopo: «che struttura, e cosa mi costa?». Un oggetto utente può stare in una stringa JSON, in un hash o in tre chiavi separate; una classifica può essere una lista che ordini nel client o un insieme che Redis tiene già ordinato. La differenza non la vedi in sviluppo con dieci chiavi: la vedi quando le chiavi sono centomila, o quando la memoria finisce (tema di un articolo successivo della serie).
Redis sceglie anche da solo, dietro le quinte, come rappresentare ciascuna struttura. Lo fa in base alla dimensione, e il comando che te lo mostra si chiama OBJECT ENCODING. Capire quando la scelta scatta è la parte che questo articolo ti consegna.
Hash: un oggetto, molti campi, un solo giro
Cos'è e cosa fa in un comando solo
Un hash è una mappa di coppie campo-valore sotto una sola chiave. Leggi o scrivi un campo con HGET e HSET, e la documentazione ne dà il costo come O(1); HGETALL è invece O(N) sul numero dei campi, quindi su un hash grande è il comando da tenere d'occhio. Il vantaggio su una stringa JSON è che aggiorni un campo senza leggere, deserializzare e riscrivere tutto, e che HINCRBY è atomico.
$ redis-cli -p 6391 hset utente:1001 nome "Mario Rossi" email mario@example.com eta 35 citta Milano
4
$ redis-cli -p 6391 object encoding utente:1001
listpack
$ redis-cli -p 6391 memory usage utente:1001
136
Il risultato (Redis 8.0.5) è un hash di quattro campi in 136 byte, rappresentato come listpack: una sequenza compatta di byte, senza i puntatori di una tabella hash. È la rappresentazione piccola.
Quanto pesa la rappresentazione grande
Per vedere cosa succede quando l'hash esce dalla forma piccola, abbasso a zero la soglia del numero di campi (solo sulla mia istanza usa-e-getta) e riscrivo lo stesso hash:
$ redis-cli -p 6391 config set hash-max-listpack-entries 0
OK
$ redis-cli -p 6391 hset utente:ht nome "Mario Rossi" email mario@example.com eta 35 citta Milano
4
$ redis-cli -p 6391 object encoding utente:ht
hashtable
$ redis-cli -p 6391 memory usage utente:ht
336
$ redis-cli -p 6391 config set hash-max-listpack-entries 512
OK
Stessi dati, 336 byte invece di 136: 2,5 volte. Su Redis 7.4.7 la forma larga dà 328 byte e quella compatta 136. La pagina sull'ottimizzazione della memoria scrive che le strutture piccole possono usare «fino a 10 volte meno memoria», in media 5, e che è un compromesso fra CPU e memoria. Il mio 2,5 è su un hash minuscolo: il fattore dipende da quanto è piccolo, e va rimisurato sui tuoi dati.
I due limiti che fanno scattare il cambio
Il passaggio da listpack a hashtable avviene quando l'hash supera una di due soglie. I valori di partenza sono, per la documentazione (e per CONFIG GET sul mio Redis 8.0.5), 512 campi e 64 byte per valore:
hash-max-listpack-entries: numero massimo di campi (default 512).hash-max-listpack-value: lunghezza massima in byte di un singolo campo o valore (default 64).
Per la proprietà hash-max-listpack-value vale la risposta alle domande che ti farai: che cos'è (un limite di dimensione per elemento), cosa accetta (un intero di byte), cosa vale se non la scrivi (64, confermato con CONFIG GET sul mio server), perché 64 qui (è il predefinito della documentazione e l'ho lasciato; la stessa pagina dice che la forma compatta è un compromesso fra CPU e memoria, quindi alzarlo sposta il conto sulla CPU) e cosa va storto (basta un solo valore più lungo per portare l'intero hash nella forma larga, per sempre in quella chiave). La prova è un solo campo da cento caratteri:
$ redis-cli -p 6391 hset lungo f "$(python3 -I -c "print('x'*100)")"
1
$ redis-cli -p 6391 object encoding lungo
hashtable
La stringa JSON non è peggiore, a parità di dimensione
Una verifica che ti toglie un pregiudizio. Lo stesso oggetto serializzato in JSON e messo in una stringa:
$ redis-cli -p 6391 set utente:json '{"nome":"Mario Rossi","email":"mario@example.com","eta":35,"citta":"Milano"}'
OK
$ redis-cli -p 6391 memory usage utente:json
136
Stessi 136 byte dell'hash compatto. L'hash non si sceglie «per risparmiare memoria» rispetto a una stringa piccola: si sceglie perché tocchi un campo senza riscrivere gli altri e perché i contatori diventano atomici. Se leggi sempre tutto l'oggetto, la stringa è più semplice.
Il caso reale: un hash per articolo, con un vettore dentro
Nel ml-service di questo sito ogni articolo indicizzato è un hash article:<id>:<lingua> con sei campi: article_id, title, slug, lang, excerpt e embedding (index_article in ml-service/app/storage/redis_vectors.py, che chiama hset). L'embedding è un vettore di 384 numeri float32, cioè 384 × 4 = 1.536 byte. Lo leggo, in sola lettura, dall'istanza di sviluppo (Redis 8.0.5):
$ redis-cli -p 6379 object encoding article:1416:en
hashtable
$ redis-cli -p 6379 hstrlen article:1416:en embedding
1536
$ redis-cli -p 6379 memory usage article:1416:en
2880
$ redis-cli -p 6379 memory usage article:1416:en samples 0
2472
$ redis-cli -p 6379 --scan --pattern 'article:*' --count 1000 | wc -l
2426
L'hash è hashtable, come ti aspetti: un campo da 1.536 byte supera di molto i 64 della soglia. Pesa 2.472 byte, di cui 1.536 di vettore. I 2.880 della riga precedente sono la stima che MEMORY USAGE restituisce senza argomenti, e perché le due cifre non coincidano lo spiega la sezione «MEMORY USAGE è una stima». Sulle prime cinquanta chiavi la media esatta è 2.500 byte, contro i 2.916 della stima:
$ redis-cli -p 6379 --scan --pattern 'article:*' --count 1000 | head -50 \
| while read k; do redis-cli -p 6379 memory usage "$k" samples 0; done \
| awk '{s+=$1} END {printf "media %.2f byte su %d chiavi\n", s/NR, NR}'
media 2500.48 byte su 50 chiavi
Per 2.426 articoli sono circa 6,1 MB: poco, ma la proporzione conta se i documenti diventano centinaia di migliaia. Il vettore pesa più di metà della chiave: i conti della memoria di un indice vettoriale partono da lì. Come questi hash diventano un indice di ricerca lo racconta l'articolo sul setup RAG con RediSearch.
Sorted Set: la classifica che Redis tiene già ordinata
Una classifica senza ordinare nel client
Un Sorted Set è un insieme di membri unici, ciascuno con un punteggio, sempre ordinato. La documentazione spiega che l'implementazione combina una skip list e una tabella hash, e che per questo ogni inserimento è O(log N) e leggere in ordine non costa nulla: l'ordine esiste già. Una classifica di quattro giocatori:
$ redis-cli -p 6391 zadd classifica 1500 anna 2300 bruno 1800 carla 900 dino
4
$ redis-cli -p 6391 zrange classifica 0 2 rev withscores
bruno
2300
carla
1800
anna
1500
$ redis-cli -p 6391 zrevrank classifica carla
1
ZRANGE ... REV restituisce i primi tre dalla cima e ZREVRANK dice che Carla è seconda (la posizione parte da 0). Il ZREVRANGE dei vecchi tutorial fa lo stesso, ma la sua pagina lo dichiara deprecato dalla 6.2.0 e indica ZRANGE con REV.
Cambiare punteggio e interrogare per intervallo
$ redis-cli -p 6391 zincrby classifica 600 carla
2400
$ redis-cli -p 6391 zrevrank classifica carla
0
$ redis-cli -p 6391 zrangebyscore classifica 1800 +inf withscores
bruno
2300
carla
2400
$ redis-cli -p 6391 object encoding classifica
listpack
Carla guadagna 600 punti e passa prima senza che tu riordini nulla: un comando, atomico. Nota l'ultima riga: anche il Sorted Set piccolo è un listpack, con soglie proprie (zset-max-listpack-entries 128 e zset-max-listpack-value 64, secondo la documentazione). Oltre i 128 elementi diventa skiplist, ed è lì che il costo cresce.
HyperLogLog: contare gli unici senza ricordarli
Il compromesso dichiarato
Un HyperLogLog stima quanti elementi distinti contiene un insieme, scambiando precisione con spazio. La documentazione dice che l'implementazione di Redis usa «fino a 12 KB» con un errore standard dello 0,81%. Si aggiunge con PFADD, si legge con PFCOUNT, si unisce con PFMERGE. Non conserva gli elementi: non puoi chiedere «c'è già l'utente X?».
La misura: centomila visitatori, tre strutture
Carico gli stessi 100.000 identificativi in tre strutture diverse, con un ciclo di shell e redis-cli --pipe (Redis 8.0.5):
$ for i in $(seq 1 100000); do echo "PFADD visitatori u$i"; done | redis-cli -p 6391 --pipe | tail -1
errors: 0, replies: 100000
$ for i in $(seq 1 100000); do echo "SADD visitatori:set u$i"; done | redis-cli -p 6391 --pipe | tail -1
errors: 0, replies: 100000
$ for i in $(seq 1 100000); do echo "ZADD punti $i u$i"; done | redis-cli -p 6391 --pipe | tail -1
errors: 0, replies: 100000
$ redis-cli -p 6391 pfcount visitatori
100425
$ redis-cli -p 6391 memory usage visitatori
14392
$ redis-cli -p 6391 scard visitatori:set
100000
$ redis-cli -p 6391 memory usage visitatori:set
4772976
$ redis-cli -p 6391 object encoding punti
skiplist
$ redis-cli -p 6391 memory usage punti
9689368
La stima dell'HyperLogLog è 100.425 invece di 100.000: errore dello 0,425%, dentro lo 0,81% dichiarato. Il costo è 14.392 byte contro i 4.772.976 del Set, cioè un fattore 330 fra due strutture che hanno visto le stesse 100.000 stringhe. Su Redis 7.4.7 HyperLogLog e Set danno gli stessi byte. Il 9.689.368 del Sorted Set, invece, è il numero di questa istanza e non sarebbe quello di un'altra: è l'argomento della sezione «MEMORY USAGE è una stima», ed è la cosa più utile che questo articolo ha da dirti.
Perché 14.392 byte se la documentazione dice 12 KB
I due numeri non si contraddicono: non misurano la stessa cosa. Un HyperLogLog in Redis è una stringa, e STRLEN te la fa vedere:
$ redis-cli -p 6391 type visitatori
string
$ redis-cli -p 6391 strlen visitatori
12304
Sono i 12.288 byte che fanno 12 KB, più 16 di intestazione. Gli altri 2.088 che portano a 14.392 sono quello che la pagina di MEMORY USAGE chiama sovraccarico amministrativo di chiave e valore, arrotondamento dell'allocatore compreso: la seconda cifra comprende la chiave, la prima no.
Quando non è la scelta giusta
- Ti serve sapere chi ha visitato, non quanti: l'HyperLogLog non conserva gli elementi.
- Un errore dello 0,81% non è accettabile (fatturazione, quote): usa un Set o una tabella del database.
- Hai poche migliaia di elementi: un Set costa qualche decina di KB (circa 48 byte a elemento nella mia misura) e ti dà numeri esatti.
Le tre voci rispondono alla stessa domanda: che cosa ti ha dato in cambio l'HyperLogLog? Memoria fissa e un numero, al prezzo dell'identità degli elementi e di un errore che non puoi azzerare. Se ti serve il «chi», o se lo 0,81% ha una conseguenza economica, hai scelto lo strumento sbagliato. La terza voce è la più facile da trascurare: con poche migliaia di elementi il risparmio assoluto è piccolo e un Set ti regala l'esattezza.
MEMORY USAGE è una stima, non un conteggio
Cinque campioni su centomila elementi
Tutti i numeri di memoria di questo articolo escono da MEMORY USAGE, e su una struttura annidata quel comando non conta: campiona. La sua pagina lo presenta come un comando che stima, ne dà la complessità come O(N) sul numero dei campioni e spiega l'opzione: SAMPLES fissa quanti elementi guardare, i campioni «vengono mediati per stimare la dimensione totale», il predefinito è 5 e con SAMPLES 0 li guarda tutti. Cinque elementi su centomila: se non rappresentano la media, l'errore viene moltiplicato per centomila.
$ redis-cli -p 6391 memory usage punti samples 5
9049368
$ redis-cli -p 6391 memory usage punti samples 50
9561368
$ redis-cli -p 6391 memory usage punti samples 100
9593368
$ redis-cli -p 6391 memory usage punti samples 1000
9593368
$ redis-cli -p 6391 memory usage punti samples 0
9580496
Mezzo megabyte fra il predefinito e il conteggio esatto, sulla stessa chiave nello stesso istante. E a cento campioni il valore è già arrivato: su centomila elementi, cento letture non costano nulla.
La stima cambia a ogni riavvio, e ripeterla non avverte
Quello che inganna è che la stima è stabile dentro un'istanza: la chiedi dieci volte e ottieni dieci volte la stessa cifra, ed è proprio questo a farti credere di avere un conteggio. Cambia fra istanze. prova-stima.sh ricostruisce cinque volte la stessa classifica, ogni volta su un processo nuovo:
#!/bin/bash
for giro in 1 2 3 4 5; do
redis-server --port 6391 --save '' --appendonly no --dir /tmp --daemonize yes 2>/dev/null
sleep 1
for i in $(seq 1 100000); do echo "ZADD punti $i u$i"; done | redis-cli -p 6391 --pipe >/dev/null
echo "giro $giro stima $(redis-cli -p 6391 memory usage punti) esatto $(redis-cli -p 6391 memory usage punti samples 0)"
redis-cli -p 6391 shutdown nosave 2>/dev/null
sleep 1
done
$ bash prova-stima.sh | grep ^giro
giro 1 stima 9689368 esatto 9582336
giro 2 stima 10009368 esatto 9586160
giro 3 stima 9049368 esatto 9589936
giro 4 stima 9689368 esatto 9584960
giro 5 stima 9369368 esatto 9581584
Guarda il giro 2: 10.009.368, cioè esattamente il numero che la prima versione di questo articolo pubblicava come «il peso della chiave». È uno dei valori possibili, non il peso. Il conteggio esatto, nello stesso giro, resta in una finestra dello 0,09%; la stima, su 8.0.5, salta di 320.000 byte per volta, ed è quanto muove un campione che pesa 16 byte in più, moltiplicato per centomila elementi e diviso per cinque campioni (sulla linea 7.4 il passo che ho misurato è la metà). Su ventidue istanze nuove la stima è andata da 9.049.368 a 10.969.368 - un'ampiezza del 21%, e sei soli valori distinti, tutti distanti un multiplo di 320.000 - mentre l'esatto non è mai uscito da 9.579.072-9.589.936.
Non è la lunghezza dei dati, è la struttura
La causa si isola. Se l'errore venisse dai membri di lunghezza diversa (u1 sono due caratteri, u100000 sette), con nomi tutti uguali di lunghezza dovrebbe sparire. prova-fissi.sh è lo stesso script con i nomi a larghezza fissa, da u000001 a u100000, e un ciclo SADD in più che costruisce un Set con gli stessi elementi:
$ bash prova-fissi.sh | grep ^giro
giro 1 zset stima 9849368 esatto 10385448 | set stima 5572968 esatto 5572968
giro 2 zset stima 9849368 esatto 10388376 | set stima 5572968 esatto 5572968
giro 3 zset stima 9849368 esatto 10390136 | set stima 5572968 esatto 5572968
Sul Set stima e conteggio coincidono, tre volte su tre: gli elementi hanno tutti la stessa forma, e cinque bastano. Sul Sorted Set no: tre volte lo stesso 9.849.368 per una chiave che pesa 10,39 MB, cioè il 5% in difetto, e su altri giri la stessa misura mi ha dato fino a 12.089.368. Tre risposte identiche e tutte sbagliate sono l'illustrazione migliore del punto di prima: ripetere non convalida. La differenza fra le due strutture è che un Sorted Set è una skip list, e in una skip list l'altezza di ogni elemento si estrae a sorte: cinque elementi non rappresentano l'altezza media. L'errore non viene dai tuoi dati, viene dalla struttura.
Il confronto fra versioni che la stima non permette
La prima versione di questo articolo metteva accanto 10.009.368 byte su 8.0.5 e 8.249.368 su 7.4.7, e concludeva che la 7.4.7 occupa meno. Quei due numeri non lo permettono: la stessa 7.4 mi ha dato anche 8.569.368, 9.049.368, 9.209.368 e 9.689.368, e il 9.689.368 è fra i valori che mi ha dato anche la 8.0.5. Con la stima predefinita le due versioni non si distinguono, e quel confronto l'ho tolto.
Col conteggio esatto si distinguono, e la cifra è un'altra: media di 9.583.695 byte su ventidue istanze di 8.0.5, 8.833.562 su dieci misure della linea 7.4 (7.4.7 in contenitore, più le immagini 7.4.9 e 7.4.12), intervalli che non si sovrappongono di un byte. Il 7,8% in meno sulla 7.4. Perché non lo so dire: sistema, architettura e allocatore sono gli stessi (jemalloc-5.3.0, da INFO memory), quindi sta dentro Redis, ma il codice non l'ho letto.
- Per un numero che finisce in un documento,
SAMPLES 0. - Ripetere la misura non la convalida: cambia fra processi, non fra chiamate. Riavvia l'istanza.
- Un byte vale per quella versione: su Redis 8.10.3 la stessa chiave misura 7.755.056 byte, e lì
SAMPLESnon cambia nulla - 1, 3, 5, 100 e 0 danno la stessa cifra.
Le tre voci dicono la stessa cosa da angoli diversi: MEMORY USAGE restituisce una cifra precisa all'apparenza e approssimata nella sostanza. La prima voce spiega come trasformarla in un conteggio, la seconda perché ripeterla non basta a fidarsi, la terza perché non puoi portarla da una versione all'altra. Quando un numero finisce in un documento, scrivi accanto comando, opzione e versione di Redis: senza, chi lo rilegge non può rifarlo.
Geospaziale: un Sorted Set con un nome diverso
Distanza e raggio
I comandi geospaziali memorizzano longitudine e latitudine e ti permettono di chiedere distanze e vicini. Aggiungo tre città italiane e misuro:
$ redis-cli -p 6391 geoadd sedi 12.4964 41.9028 roma 9.1900 45.4642 milano 18.1696 40.3515 lecce
3
$ redis-cli -p 6391 type sedi
zset
$ redis-cli -p 6391 geodist sedi roma milano km
477.0191
$ redis-cli -p 6391 geosearch sedi fromlonlat 12.5 42.0 byradius 700 km asc withdist
roma
10.8153
milano
468.1267
lecce
508.7101
Il TYPE è zset. La pagina di GEOADD spiega che il punteggio è un intero a 52 bit ottenuto intrecciando i bit di latitudine e longitudine (geohash), e che per questo non esiste un GEODEL: si toglie un luogo con ZREM. Il risultato di GEOSEARCH è ordinato per distanza dal punto.
GEORADIUS è deprecato
Molti tutorial usano ancora GEORADIUS. La pagina del comando lo segnala come deprecato dalla 6.2.0 e indica GEOSEARCH con BYRADIUS come sostituto. L'ho provato su entrambe le versioni e funziona ancora, ma in codice nuovo non ha ragione di esserci.
$ redis-cli -p 6391 georadius sedi 12.5 42.0 700 km asc withdist | head -3
roma
10.8153
milano
Cosa guardare su una chiave che non conosci
TYPE: la struttura (hash, zset, string).OBJECT ENCODING: la rappresentazione scelta da Redis (listpack,hashtable,skiplist,raw).MEMORY USAGE: i byte di chiave e valore, sovraccarico compreso - ma su hash, Set, Sorted Set e liste è una stima su cinque elementi, eSAMPLES 0la rende un conteggio.HLEN,ZCARD,SCARD,HSTRLEN: quanti elementi e quanto è lungo il più sospetto.
Le quattro verifiche si leggono in ordine perché ciascuna restringe la successiva: TYPE ti dice quali comandi hanno senso, OBJECT ENCODING se sei sotto o sopra la soglia di compattazione, MEMORY USAGE quanto costa, e solo allora i comandi di lunghezza indicano quale elemento spiega il costo. Sono tutte di sola lettura: puoi lanciarle su un'istanza che non è tua senza cambiare nulla, e per questo sono le prime cose che faccio.
Come scegliere: la tabella che userei io
Tre domande in questo ordine: ti serve l'elemento singolo o solo un numero? Ti serve un ordine? L'oggetto si modifica a pezzi?
- Un oggetto con campi che cambiano da soli: hash. Costo di lettura O(1) per campo.
- Un oggetto letto sempre per intero: stringa (JSON o binario). 136 byte, come l'hash compatto.
- Una classifica o una finestra di tempo: Sorted Set, O(log N) per scrittura.
- «Quanti sono?» e non «chi sono?»: HyperLogLog, 12 KB di registri (14.392 byte di chiave, misurati) e circa lo 0,8% di errore.
- «Chi c'è nel raggio di X km?»: geospaziale, cioè un Sorted Set specializzato.
La tabella non confronta tecnologie, abbina la forma del tuo accesso alla struttura che lo rende economico. Hash e stringa, per esempio, costano lo stesso nella mia misura (136 byte): li separa il modo in cui leggi, per campo o per intero. Se due righe ti sembrano entrambe vere, scegli quella che rende semplice il comando che eseguirai più spesso, e lascia che la memoria sia il criterio di spareggio, non il primo.
Il trade-off, e quando non usarle
Per i vettori degli articoli l'hash non è una scelta di memoria: a dati piccoli una stringa pesa lo stesso. La documentazione dei vettori dice che vettori e metadati vivono in hash o in oggetti JSON, e l'hash è la più semplice: un campo binario accanto a quelli di testo, senza serializzare nulla. Se all'epoca si valutò il JSON non lo so, e non lo scrivo come fatto. Dove serve l'elenco dei visitatori pago il Set. Su un Sorted Set da centomila membri accetto i suoi 9,58 MB, perché la classifica già ordinata è ciò che compro: se non ti serve l'ordine, paghi per qualcosa che non usi.
Una nota onesta: il sito non usa classifiche, HyperLogLog né comandi geospaziali. Li mostro perché la domanda «che struttura?» è la stessa che dovrai farti per gli usi che il sito ha davvero. Il lavoro che ha dentro Redis, dagli embedding al lock, è nel resto della serie.
Cosa sai fare adesso
Sai guardare una chiave con TYPE, OBJECT ENCODING e MEMORY USAGE e dire quanto pesa e perché. Sai che un solo valore sopra i 64 byte sposta l'intero hash in una rappresentazione che, a parità di dati, nei miei esperimenti costa 2,5 volte. Sai che un HyperLogLog conta centomila elementi in 14 KB con meno dell'1% di errore, e che GEORADIUS è deprecato. E sai la cosa che mi è costata un numero da correggere: che su una struttura annidata MEMORY USAGE campiona cinque elementi, che serve SAMPLES 0 quando il numero conta, e che due versioni di Redis non si confrontano con una stima. Il passo successivo è sapere cosa accade a quelle chiavi quando Redis si riavvia, tema dell'articolo su RDB, AOF e riavvio, mentre cosa accade quando la memoria finisce è in maxmemory, eviction e OOM. Per la messaggistica fra servizi c'è Pub/Sub o Streams, per le operazioni atomiche Lua con EVAL, e per misurare memoria e latenza di un'istanza che non conosci latenza, SLOWLOG e memoria per chiave.
Hai una struttura dati che non sai come modellare? Prenota una call →
Domande frequenti
Quanta memoria occupa un hash Redis piccolo?
Su Redis 8.0.5 un hash di quattro campi occupa 136 byte in rappresentazione listpack e 336 byte se è costretto a hashtable. Su 7.4.7 sono 136 e 328 byte. Il passaggio avviene oltre 512 campi o con un valore più lungo di 64 byte.
HyperLogLog è preciso?
Non è esatto: la documentazione di Redis dichiara un errore standard dello 0,81% con al massimo 12 KB. In una misura con 100.000 elementi unici ha stimato 100.425, con errore dello 0,425% e 14.392 byte, contro 4.772.976 byte di un Set.
GEORADIUS si può ancora usare?
Funziona ancora su Redis 8.0.5 e 7.4.7, ma è deprecato dalla 6.2.0. La documentazione indica GEOSEARCH con BYRADIUS come sostituto da usare nel codice nuovo.
Fonti
- Redis, HyperLogLog - fino a 12 KB e errore standard dello 0,81%, consultata il 2026-11-13.
- Redis, Sorted sets - skip list più tabella hash e inserimento O(log N), consultata il 2026-11-08.
- Redis, Memory optimization - le soglie di
hash-max-listpack-*e il fattore «fino a 10 volte» di risparmio, consultata il 2026-11-08. - Redis, GEOADD - punteggio a 52 bit (geohash) e rimozione con
ZREM, consultata il 2026-11-08. - Redis, ZREVRANGE - deprecato dalla 6.2.0, consultata il 2026-11-13.
- Redis, Vectors - vettori e metadati in hash o JSON, consultata il 2026-11-08.
- Redis, GEORADIUS - deprecato dalla 6.2.0, sostituito da GEOSEARCH, consultata il 2026-11-13.
- Redis, MEMORY USAGE - il comando «stima» la memoria, complessità O(N) sul numero dei campioni,
SAMPLESpredefinito a 5 eSAMPLES 0per guardarli tutti, consultata il 2026-11-13. - Redis, OBJECT ENCODING - le rappresentazioni di hash e Sorted Set, consultata il 2026-11-08.
- Redis, release su GitHub - la versione corrente (8.10.3, pubblicata il 2026-10-26), consultata il 2026-11-13 con l'interfaccia di programmazione di GitHub.
- Misure: i comandi dei blocchi sopra, eseguiti il 2026-11-08 su Redis 8.0.5 (nativo) e 7.4.7 (
redis/redis-stack-server:latest), e la lettura diml-service/app/storage/redis_vectors.py, funzioneindex_article.
Le fonti dell'elenco sono pagine della documentazione ufficiale, e per questo portano la data di consultazione: se una frase non la ritrovi, è la pagina che si è mossa e non la citazione. L'ultima voce è di natura diversa, perché sono comandi e righe di codice che puoi rieseguire tu. Dove le due famiglie dovessero contraddirsi, vale il comando eseguito sulla tua versione di Redis.

Commenti
Caricamento commenti...
Accedi per commentare