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

Conosci il database Redis:iterare sulle chiavi

Una delle cose che spesso confonde gli utenti che hanno familiarità con altri database quando provano Redis, è la mancanza di visibilità nel database:non ci sono set di tabelle o raccolte da vedi, solo uno spazio chiave semplice e piatto che potrebbe (potenzialmente) avere milioni di chiavi. La capacità di eseguire iterazioni a basso costo su questo spazio chiave diventa quindi molto importante per familiarizzare con i contenuti del database.

L'iterazione sullo spazio della chiave Redis ha altri casi d'uso importanti, alcuni dei quali vengono in mente:

  • raccolta di rifiuti o ripulitura di chiavi che corrispondono a un determinato schema
  • Spostamento dei dati e modifiche allo schema o spostamento di un determinato set di chiavi in ​​un'altra struttura di dati
  • debug, campionamento dei dati, correzioni dei dati o ricerca e correzione di tutte le chiavi che sono state incasinate da una recente modifica

In questo post, analizzeremo in profondità varie opzioni di iterazione dello spazio chiave disponibili in Redis.

O(N) Iteratori:CHIAVI

Il comando Redis KEYS restituisce tutte le chiavi nel database che corrispondono a un modello (o tutte le chiavi nello spazio delle chiavi). Comandi simili per recuperare tutti i campi memorizzati in un hash è HGETALL e per recuperare tutti i membri di uno SMEMBERS. Le chiavi in ​​Redis stesse sono memorizzate in un dizionario (noto anche come tabella hash). Il comando KEYS funziona eseguendo l'iterazione su questo dizionario e inviando tutto ciò che corrisponde al pattern come una singola risposta Array. Gli altri comandi funzionano in modo simile.

Le prestazioni di tale operazione dipendono dalle dimensioni della raccolta, ovvero O(N). Pertanto, l'uso di KEYS è fortemente sconsigliato in ambienti di produzione con un numero elevato di chiavi. Redis essendo a thread singolo, viene bloccato durante questa iterazione bloccando così altre operazioni. Pertanto, KEYS dovrebbe essere utilizzato solo per il debug e altre occasioni speciali in cui le prestazioni non sono un problema (come quando il database è stato portato offline per applicare una correzione dei dati). L'altra cosa importante da ricordare su questo algoritmo è che invia tutte le chiavi corrispondenti insieme come un'unica risposta. Questo potrebbe essere estremamente conveniente quando lo spazio chiave è piccolo ma creerà più problemi su uno spazio chiave grande. KEYS, tuttavia, è un comando preferito dagli sviluppatori nei propri ambienti di sviluppo.

CHIAVI in azione:

127.0.0.1:6379[1]> MSET one 1 two 2 three 3 four 4
OK
# All the keys
127.0.0.1:6379[1]> keys *
1) "four"
2) "three"
3) "two"
4) "one"
# keys that begin with the letter 't'
127.0.0.1:6379[1]> keys t*
1) "three"
2) "two"
# keys that have a 'ee' in them
127.0.0.1:6379[1]> keys *ee*
1) "three"

Iteratori basati su cursore:SCAN

I comandi SCAN e i suoi fratelli, SSCAN (per gli insiemi), HSCAN (per gli hash) e ZSCAN (per gli insiemi ordinati) forniscono l'approccio basato sul cursore per l'iterazione sulle strutture di dati Redis. Sono disponibili in Redis dalla 2.8.0.

Le chiavi vengono restituite in iterazioni incrementali con garanzia di tempo costante per ogni iterazione. Un cursore (in questo caso un numero intero) viene restituito quando le iterazioni vengono inizializzate e viene restituito un cursore aggiornato e ogni iterazione. Un ciclo di iterazione inizia quando il cursore è impostato su 0 nella richiesta SCAN e termina quando il cursore restituito dal server è 0.  A causa delle sfumature dell'architettura Redis e dell'implementazione dell'algoritmo del cursore, ecco alcune particolarità di questo approccio:

  • Un'iterazione completa recupera sempre tutti gli elementi che erano presenti nella raccolta dall'inizio alla fine di un'iterazione completa.
  • Un'iterazione completa non restituisce mai alcun elemento che NON era presente nella raccolta dall'inizio alla fine di un'iterazione completa.
  • Un dato elemento può essere restituito più volte. Spetta all'applicazione gestire il caso di elementi duplicati
  • Gli elementi che non erano costantemente presenti nella raccolta durante un'iterazione completa, possono essere restituiti o meno:non è definito.
  • Un numero di elementi restituiti durante ogni conteggio varia e può essere anche 0. Tuttavia, l'iterazione non è completa finché il server non restituisce il valore del cursore 0.
  • Il COUNT L'opzione può essere utilizzata per limitare il numero di elementi restituiti in ogni iterazione. Il valore predefinito è 10. Tuttavia, è considerato solo un suggerimento e non viene applicato in tutti i casi. Il valore COUNT può essere modificato durante ogni chiamata di iterazione.
  • La PARTITA l'opzione consente di specificare modelli come consente il comando KEYS.
  • L'implementazione del cursore è completamente senza stato sul lato server. Ciò consente (potenzialmente) infinite iterazioni di iniziare in parallelo. Inoltre, non ci sono requisiti per garantire che un'iterazione continui fino alla fine e possa essere interrotta in qualsiasi momento.

Nonostante le sue peculiarità, SCAN è un comando molto utile e il comando giusto da scegliere per le iterazioni dello spazio chiave per la maggior parte dei casi d'uso.

SCAN è un comando molto utile e il comando giusto da scegliere per le iterazioni dello spazio chiave in #RedisClick To Tweet

SCANSIONE in azione

127.0.0.1:6379[1]> flushdb
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> debug populate 33
OK
127.0.0.1:6379[1]> scan 0 COUNT 5
1) "4"
2) 1) "key:1"
   2) "key:9"
   3) "key:13"
   4) "key:29"
   5) "key:23"
127.0.0.1:6379[1]> scan 4 
1) "42"
2)  1) "key:24"
    2) "key:28"
    3) "key:18"
    4) "key:16"
    5) "key:12"
    6) "key:2"
    7) "key:6"
    8) "key:31"
    9) "key:27"
   10) "key:19"
127.0.0.1:6379[1]> scan 42
1) "9"
2)  1) "key:3"
    2) "key:4"
    3) "key:20"
    4) "key:8"
    5) "key:32"
    6) "key:5"
    7) "key:26"
    8) "key:10"
    9) "key:21"
   10) "key:14"
127.0.0.1:6379[1]> scan 9 COUNT 100
1) "0"
2) 1) "key:25"
   2) "key:30"
   3) "key:22"
   4) "key:17"
   5) "key:15"
   6) "key:0"
   7) "key:11"
   8) "key:7"

Under the Hood

L'algoritmo utilizzato da SCAN (e dai suoi comandi fratelli) per eseguire la scansione è intrigante e porta ad alcune delle caratteristiche del comando che abbiamo descritto sopra. Antirez lo ha descritto ad alto livello nel suo post sul blog ed è spiegato (leggermente meglio) nei commenti sopra l'implementazione (funzione dictScan). Descriverlo in dettaglio renderà questo post troppo lungo, quindi fornirò una descrizione sufficiente per renderne evidenti le implicazioni.

  • La maggior parte delle strutture di dati Redis sono rappresentate internamente come dizionari (almeno parzialmente nel caso di set ordinati). Sono implementati come tabelle hash power-of-two con concatenamento per le collisioni. La sfida nello scrivere un algoritmo iterativo basato sul cursore qui è essere in grado di gestire la crescita e la riduzione dell'hash senza sacrificare i principi Redis di semplicità (dell'API) e velocità.
  • SCAN fondamentalmente scansiona un mucchio di hash bucket ogni iterazione e restituisce gli elementi che corrispondono al modello in quelli. Poiché esamina solo un elenco fisso di bucket, alcune iterazioni temporali potrebbero non restituire alcun valore.
  • Il cursore restituito è fondamentalmente un offset nella tabella hash che viene iterata. Si occupa della crescita e della riduzione delle tabelle hash (cioè il rehashing) mediante una manipolazione intelligente dei bit di livello superiore dell'offset aumentando l'offset insieme alle proprietà della tabella hash. Le implicazioni di questo approccio sono che i nuovi elementi aggiunti durante l'iterazione possono o non possono essere restituiti. Tuttavia, il cursore stesso non avrebbe bisogno di essere riavviato in caso di modifica delle dimensioni della tabella hash.
  • Un determinato bucket deve essere visitato solo una volta e tutte le sue chiavi devono essere restituite in una volta sola. Questo è ancora una volta per garantire che il ridimensionamento dell'hash (cioè il rehashing) non complichi il progresso dell'iterazione. Tuttavia, ciò fa sì che l'argomento COUNT non sia rigorosamente applicabile.
  • Poiché l'approccio di cui sopra è completamente senza stato sul lato server, implica sostanzialmente che le iterazioni possono essere interrotte o che un numero enorme di iterazioni può essere avviato in parallelo senza aumentare l'utilizzo della memoria.

Riepilogo

Ad alto livello, sono disponibili due scelte per scorrere lo spazio chiave Redis sono:

  1. Utilizza KEYS quando le prestazioni non sono un problema o quando lo spazio chiave è di dimensioni ragionevoli.
  2. Tutte le altre volte, usa SCAN.
Per scorrere lo spazio chiave #Redis, usa KEYS quando le prestazioni non sono un problema, altrimenti usa SCANClick To Tweet

Sapevi che ora supportiamo l'hosting per Redis™*? Ottieni un hosting completamente gestito per Redis™ nella sicurezza del tuo account cloud e sfrutta i crediti AWS/Azure per le tue implementazioni Redis™.