Padroneggiare GET e SET di Redis: Operazioni di Base sui Dati
Padroneggia le basi della gestione dei dati in Redis con questa guida completa ai comandi `GET` e `SET`. Impara l'archiviazione e il recupero di base delle stringhe, ed esplora opzioni avanzate essenziali come l'impostazione atomica (`NX`/`XX`) e la scadenza integrata delle chiavi (`EX`/`PX`). Scopri come questi comandi fondamentali sono cruciali per costruire livelli di caching ad alte prestazioni.
Padroneggiare GET e SET di Redis: Operazioni di Base sui Dati
GET e SET di Redis sembrano fin troppo semplici. Scrivi un valore. Leggi un valore. Nelle applicazioni reali, questi due comandi sono alla base di sessioni di login, flag di funzionalità, limiti di velocità, voci di cache, lock a breve durata e scorciatoie del tipo "per favore non interrogare di nuovo il database".
I dettagli contano perché Redis fa esattamente ciò che chiedi. Se sovrascrivi accidentalmente una chiave, non ti chiederà se lo intendevi. Se dimentichi una scadenza su dati in cache, potrebbero vivere più a lungo della fonte dati. Se tratti una chiave mancante come una stringa vuota, la tua applicazione potrebbe prendere la decisione sbagliata.
Il Modello Chiave-Valore di Redis
Prima di immergerci nei comandi, è importante ricordare che Redis opera su un semplice modello chiave-valore. Ogni dato (il valore) è accessibile tramite un identificatore univoco (la chiave). Le chiavi sono stringhe e i valori possono essere vari tipi di dati (stringhe, liste, insiemi, hash, ecc.). SET e GET si occupano principalmente del tipo di dato Stringa, che è il tipo più basilare e frequentemente utilizzato in Redis.
1. Impostare i Dati: Il Comando SET
Il comando SET viene utilizzato per assegnare un valore a una chiave. Se la chiave contiene già dei dati, il comando SET sovrascriverà il valore esistente. La sua sintassi di base è semplice.
Sintassi e Utilizzo di Base
La forma più semplice richiede solo la chiave e il valore:
SET key value
Esempio: memorizzare il nome visualizzato di un utente:
127.0.0.1:6379> SET user:100:name "Alice Johnson"
OK
127.0.0.1:6379> GET user:100:name
"Alice Johnson"
Opzioni Avanzate di SET: NX, XX e Scadenza
La potenza di SET deriva dai suoi argomenti opzionali, che consentono l'impostazione condizionale atomica e la gestione del time-to-live (TTL). Queste opzioni sono fondamentali per implementare correttamente lock e cache.
Impostazione Condizionale: NX e XX
Queste opzioni controllano quando avviene un'operazione di set, prevenendo sovrascritture accidentali o assicurando che una sovrascrittura avvenga solo se la chiave esiste.
NX(Not Exists - Non Esiste): Imposta la chiave solo se non esiste già. Utile per operazioni di "sola creazione" e pattern di lock semplici.SET my_lock_key some_unique_value NXXX(Exists - Esiste): Imposta la chiave solo se esiste già. Utile quando si vuole aggiornare una chiave nota senza crearne accidentalmente una nuova.SET session:token:456 new_value XX
B. Impostazione del Tempo di Scadenza (TTL)
Per gestire la memoria e implementare la cache basata sul tempo, puoi impostare un tempo di scadenza direttamente all'interno del comando SET. Questo è molto più efficiente che impostare la chiave e poi chiamare EXPIRE separatamente.
EX secondi: Imposta il tempo di scadenza in secondi.PX millisecondi: Imposta il tempo di scadenza in millisecondi.EXAT timestamp: Imposta la scadenza a un timestamp Unix specifico (secondi).PXAT timestamp: Imposta la scadenza a un timestamp Unix specifico (millisecondi).
Esempio: impostare una chiave che scade tra un'ora:
127.0.0.1:6379> SET cache:product:500 "Product Details" EX 3600
OK
127.0.0.1:6379> TTL cache:product:500
(integer) 3598
Usa SET key value EX N o PX N per le voci della cache. Rende la scrittura e la scadenza parte di un unico comando, evitando il comune bug in cui l'applicazione scrive una chiave di cache e si blocca prima di chiamare EXPIRE.
Combinare le Opzioni
Tutte le opzioni possono spesso essere combinate per operazioni atomiche complesse:
# Imposta la chiave solo se non esiste e falla scadere tra 60 secondi
SET my_config_setting "active" NX EX 60
2. Recuperare i Dati: Il Comando GET
Il comando GET recupera il valore stringa associato a una data chiave. È una delle operazioni più veloci eseguite da Redis, spesso completata in microsecondi.
Sintassi e Utilizzo di Base
GET key
Esempio: Recuperare il nome utente memorizzato
127.0.0.1:6379> GET user:100:name
"Alice Johnson"
Gestione delle Chiavi Inesistenti
Se la chiave non esiste, GET restituisce una risposta speciale che indica che non è stato trovato nulla:
127.0.0.1:6379> GET non_existent_key
(nil)
Nel codice dell'applicazione, ricevere (nil) è il modo standard per determinare che i dati mancano, di solito innescando un cache miss in cui l'applicazione deve recuperare i dati dalla fonte primaria (come un database) e successivamente riscriverli in Redis.
Ottenere un Valore Modificando la Scadenza: GETEX
Il comando GET di base restituisce solo il valore. Non restituisce il TTL rimanente. Se hai bisogno del TTL, usa TTL key o PTTL key come comando separato.
GETEX è diverso: restituisce il valore e modifica la scadenza della chiave contemporaneamente. È utile per il comportamento di sessione scorrevole, in cui ogni lettura estende la durata della sessione.
GETEX session:abc123 EX 1800
Questo legge il valore della sessione e reimposta la scadenza a 30 minuti. Non usarlo casualmente per letture di cache normali, perché ogni lettura diventa un'operazione simile a una scrittura che modifica i metadati della chiave.
3. Applicazione Pratica: Caching con GET e SET
Il caso d'uso fondamentale per GET e SET è l'implementazione di un semplice pattern cache-aside.
Passaggi nella logica dell'applicazione:
- Prova
GET product:500. - Se Redis restituisce un valore, decodificalo e restituiscilo.
- Se Redis restituisce nil, recupera il prodotto dal database primario.
- Memorizza il risultato serializzato con
SET product:500 <json> EX 300. - Restituisci il risultato al chiamante.
Questo pattern può ridurre il carico del database, ma crea anche una finestra di dati obsoleti. Se il prodotto cambia nel database, Redis potrebbe ancora servire il vecchio valore fino alla scadenza del TTL o fino a quando la tua applicazione non invalida la chiave. Scegli i TTL in base a quanto i dati possono essere errati, non solo a quanto traffico vuoi risparmiare.
Nominare le Chiavi Senza Creare Caos
Redis non richiede una convenzione di denominazione, ma il tuo futuro te la richiederà. Un pattern leggibile come user:100:name, product:500:summary o rate:user:100:login rende il debug con redis-cli molto più semplice.
Mantieni le chiavi chiare e ragionevolmente corte. Risparmiare qualche byte nominando una chiave u:100:n raramente vale la confusione, a meno che tu non operi su scala molto grande e abbia misurato l'overhead delle chiavi. Per la maggior parte dei team, la coerenza è più importante dell'estrema brevità.
Fai attenzione ai valori forniti dall'utente nelle chiavi. Se un indirizzo email, un URL o un nome tenant diventa parte della chiave, normalizzalo prima. Altrimenti, piccole differenze di formattazione possono creare voci di cache duplicate:
[email protected]
[email protected]
[email protected]
Tutti questi potrebbero rappresentare lo stesso utente per la tua applicazione, ma chiavi diverse per Redis.
Sovrascritture, Valori Vuoti e Nil
SET sovrascrive per impostazione predefinita:
SET config:mode "safe"
SET config:mode "fast"
GET config:mode
Il valore finale è "fast". Se la sovrascrittura fosse pericolosa, usa NX o XX.
Distinguere anche una chiave mancante da un valore vuoto. Nil di Redis significa che la chiave manca. Una stringa vuota è un valore memorizzato reale:
SET user:100:nickname ""
GET user:100:nickname
La tua libreria client potrebbe rappresentarli diversamente: null, None, nil, una stringa di byte vuota o una stringa vuota. Controlla il comportamento del client invece di indovinare.
Pattern di Lock Sicuro, Con un Avvertimento
Vedrai spesso questo pattern:
SET lock:invoice:123 "worker-7:1700000000" NX EX 30
Significa "crea questo lock solo se non esiste e fallo scadere dopo 30 secondi". La scadenza non è opzionale. Senza di essa, un worker crashato può lasciare un lock per sempre.
Per semplici configurazioni Redis a istanza singola, questo pattern è spesso sufficiente per il coordinamento a basso rischio. Per il distributed locking critico in presenza di guasti, deriva dell'orologio e più nodi Redis, usa una libreria ben recensita e comprendi i suoi compromessi. Un bug del lock può diventare un bug di corruzione dei dati.
Debug con redis-cli
Quando un percorso GET o SET si comporta in modo strano, controlla direttamente la chiave:
redis-cli GET product:500
redis-cli TTL product:500
redis-cli TYPE product:500
TYPE è utile perché GET funziona solo su valori stringa. Se la chiave contiene un hash, una lista, un insieme o un insieme ordinato, Redis restituisce un errore di tipo errato. Di solito significa che due parti dell'applicazione stanno usando lo stesso nome di chiave per scopi diversi.
Se devi ispezionare diverse chiavi correlate durante lo sviluppo, SCAN è più sicuro di KEYS su un server di produzione occupato:
redis-cli SCAN 0 MATCH 'product:500:*' COUNT 100
KEYS * può bloccare Redis mentre scansiona il keyspace. Va bene su una piccola istanza locale. È una cattiva abitudine in produzione.
Scegliere i TTL nei Sistemi Reali
La scelta del TTL è una decisione di prodotto e operativa, non un trucco di Redis. Una cache del profilo utente potrebbe tollerare cinque minuti di obsolescenza. Un controllo dei permessi potrebbe aver bisogno di un TTL molto più breve o di un'invalidazione esplicita. Un flag di funzionalità potrebbe aver bisogno di aggiornamenti quasi immediati se controlla un rollout rischioso.
Ecco tre pattern comuni:
SET cache:product:500 "<json>" EX 300
SET session:abc123 "<json>" EX 1800
SET rate:user:100:login "1" EX 60 NX
La cache del prodotto può essere un po' obsoleta. La sessione ha una durata chiara. La chiave del limite di velocità usa NX in modo che il primo tentativo crei la finestra e i tentativi successivi possano incrementare o controllare le chiavi correlate a seconda del design.
Evita le chiavi "cache per sempre" a meno che tu non abbia un chiaro percorso di invalidazione. Una cache per sempre diventa eventualmente un secondo database, di solito senza la disciplina operativa che applichi al database reale.
Dettagli di Serializzazione
Le stringhe Redis sono binary-safe. Possono contenere JSON, MessagePack, dati compressi, contatori o testo semplice. Il comando non si preoccupa. La tua applicazione sì.
JSON è facile da ispezionare:
SET product:500 "{\"id\":500,\"name\":\"Desk Lamp\"}" EX 300
I formati binari possono risparmiare spazio o CPU in alcune applicazioni, ma rendono il debug da terminale più difficile. La compressione può aiutare per dati grandi e ripetuti, ma aggiunge anche costo CPU e potrebbe nascondere il fatto che stai memorizzando nella cache oggetti troppo grandi.
Per i contatori, non leggere con GET, aggiungere nell'applicazione e scrivere con SET se più client possono aggiornare la stessa chiave. Usa invece i comandi atomici per contatori di Redis:
INCR page:view:500
EXPIRE page:view:500 86400
Per i contatori con scadenza al primo inserimento, usa una transazione o un piccolo script Lua se hai bisogno di un comportamento rigoroso. Altrimenti, sii chiaro sulla race condition che stai accettando.
Evitare Collisioni di Chiavi
Due team che usano lo stesso database Redis possono accidentalmente riutilizzare una chiave come user:100. Un team memorizza JSON con SET; un altro memorizza campi con HSET. La successiva GET restituisce un errore di tipo errato ed entrambi i team perdono tempo.
I namespace aiutano:
shop:prod:user:100:profile
shop:prod:session:abc123
billing:prod:invoice:9001
Non hai bisogno di chiavi dolorosamente lunghe, ma includi abbastanza contesto per evitare collisioni tra ambienti, servizi e tipi di dati. Se condividi Redis tra applicazioni, una convenzione di denominazione fa parte dell'interfaccia.
Quando Non Usare GET e SET
Le stringhe sono il punto di partenza, non l'intero modello Redis. Se aggiorni frequentemente un campo all'interno di un blob JSON più grande, un hash potrebbe essere più pulito:
HSET user:100 name "Alice Johnson" email "[email protected]"
HGET user:100 email
Se hai bisogno di eventi ordinati, usa stream o liste. Se hai bisogno di controlli di appartenenza, usa insiemi. Se hai bisogno di classifiche, usa insiemi ordinati. Riscrivere un'intera stringa serializzata per ogni piccola modifica è semplice all'inizio, ma può diventare costoso e scomodo man mano che l'oggetto cresce.
Una Piccola Checklist Prima del Rilascio
Prima di rilasciare un nuovo percorso GET e SET, fai alcune semplici domande.
- Qual è il nome esatto della chiave?
- Due servizi possono accidentalmente usare la stessa chiave?
- La chiave dovrebbe scadere?
- Cosa succede quando Redis restituisce nil?
- La sovrascrittura è accettabile o la scrittura dovrebbe usare
NXoXX? - Il valore è abbastanza piccolo da essere letto e scritto come una singola stringa?
- Puoi fare il debug del valore da
redis-clise il comportamento in produzione sembra sbagliato?
Queste domande catturano la maggior parte degli errori di base con le stringhe Redis prima che diventino incidenti. La sintassi del comando è facile. Il ciclo di vita intorno alla chiave è dove di solito si nascondono i bug.
GET e SET sono comandi piccoli con molto peso operativo. Usa le scadenze per i dati della cache, usa NX o XX quando le sovrascritture contano, tratta nil come uno stato separato e mantieni i nomi delle chiave abbastanza coerenti in modo che qualcuno possa farne il debug da un terminale. Una volta che le stringhe iniziano a sembrare strette, sposta i campi correlati in hash e usa la struttura dati che corrisponde al pattern di accesso.