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

Introduzione alle strutture dati Redis:insiemi

Redis (Remote Dictionary Server) è un archivio di valori-chiave in memoria estremamente popolare che fornisce anche durabilità, partizionamento, replica e una serie di altre funzionalità opzionali. Attualmente è il database chiave-valore più popolare ed è noto per la sua semplicità, il basso footprint di memoria e la bassa curva di apprendimento. Redis viene anche definito server di struttura dati e supporta operazioni atomiche su strutture dati come hash, elenchi, set, set ordinati, bitmap e hyperlog. In questo post, esamineremo il tipo di dati impostato fornito da Redis insieme al suo utilizzo e ai casi d'uso della vita reale.

Set Redis

I Redis Set sono raccolte di stringhe non ordinate (una stringa è il valore Redis di base che può contenere quasi tutto) che fornisce addizioni, rimozioni e controlli di appartenenza costanti. Redis supporta anche operazioni di unione, intersezione e sottrazione ragionevolmente veloci tra insiemi. Come previsto, non consente valori ripetuti.

Ecco alcuni esempi di insiemi Redis in azione dal redis-cli . Ecco un riepilogo delle rappresentazioni chiave nell'esempio seguente:

  • utenti:tutti rappresenta un insieme di tutti gli utenti registrati su un sito web.
  • utenti:actv rappresenta gli utenti attivi.
  • users:inactv rappresenta gli utenti inattivi (utenti che non visitano il sito da un po' di tempo).
# sadd key member [member ...] : add members to a set
127.0.0.1:6379> sadd users:all 11 12 13 14 15 Rocket Pocket Socket
(integer) 8
127.0.0.1:6379> type users:all
set
# smembers key: get all members of a set
127.0.0.1:6379> smembers users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "Rocket"
7) "12"
8) "15"
# sismember key member: is the given value a member of the set?
127.0.0.1:6379> sismember users:all 00
(integer) 0
127.0.0.1:6379> sismember users:all 11
(integer) 1
127.0.0.1:6379> sismember users:all Socket
(integer) 1
127.0.0.1:6379> sadd users:inactv 11 12 13
(integer) 3
# sinter key [key ...]: Intersection of multiple sets
# Similar: sinterstore stores the result of intersection of sets to a new set
127.0.0.1:6379> sinter users:all users:inactv
1) "11"
2) "12"
3) "13"
# scard key: cardinality of the set i.e. number of members present in the set
127.0.0.1:6379> scard users:all
(integer) 8
# sdiff key [key ...] : Subtract multiple sets
# Similar: sdiffstore: subtract and store result in a new destination set
127.0.0.1:6379> sdiff users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "12"
7) "Rocket"
8) "15"
127.0.0.1:6379> sdiff users:all users:inactv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
# sdiffstore destination key [key ...]
127.0.0.1:6379> sdiffstore users:actv users:all users:inactv
(integer) 5
127.0.0.1:6379> smembers users:actv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
127.0.0.1:6379> sdiff users:all users:actv users:inactv
(empty list or set)
# smove source destination member: move a member from source set to destination.
127.0.0.1:6379> smove users:inactv users:actv 11
(integer) 1
127.0.0.1:6379> smembers users:actv
1) "Pocket"
2) "11"
3) "Socket"
4) "14"
5) "Rocket"
6) "15"

Altri importanti comandi di set includono:

  • SUNION – imposta l'unione
  • SPOP – rimuove casualmente un elemento
  • SREM:rimuovi uno o più elementi

L'elenco completo dei comandi Redis relativi a set può essere trovato qui.

Interni Redis

Redis memorizza internamente i set come dizionari. I dizionari in Redis sono implementati come tabelle hash che utilizzano la funzione hash MurmurHash2 e crescono tramite il ridimensionamento incrementale. Le collisioni hash vengono gestite mediante concatenamento. Gli insiemi hanno una codifica speciale per gli insiemi piccoli quando tutti i membri di un insieme sono nella radice 10 nell'intervallo # di interi con segno a 64 bit chiamati IntSets. Questo è essenzialmente un array ordinato di numeri interi. Le ricerche all'interno dell'array vengono eseguite tramite la ricerca binaria. Ovviamente, questa implementazione è efficiente per set molto piccoli. La dimensione fino a cui viene utilizzata questa codifica è regolata da set-max-intset-entries parametro di configurazione. Il valore predefinito è 512. Una buona descrizione delle strutture dati interne utilizzate da Redis può essere trovata qui.

Applicazioni Redis

Ecco un piccolo elenco di alcune delle possibili applicazioni Redis Set:

  • Come set, può essere utilizzato per tracciare oggetti unici:
    • Tutti gli indirizzi IP univoci che visitano il tuo sito.
    • Tutte le istanze di lavoro univoche attualmente in un determinato stato, ecc.
  • Anche in questo caso, come insieme, può essere usato per denotare come "appartiene a" o relazione simile:
    • Tutti gli SKU appartenenti a una particolare categoria.
    • Tutti gli oggetti con un tag particolare, ecc.
  • Gli insiemi possono essere usati solo per combinare relazioni, ad esempio unione/intersezione/sottrazione di insiemi:
    • Tutti gli SKU che appartengono alla categoria delle t-shirt, ma non una sottocategoria dei colli a polo.

Prendiamo un esempio di vita reale ed esploriamo ulteriormente i casi d'uso correlati.

Visual Profiler per il tuo eBook Store

Diciamo che sei il proprietario di un negozio di libri online molto grande che elenca milioni di titoli. Il tuo database principale è MongoDB e funziona abbastanza bene per la maggior parte dei tuoi casi d'uso con l'uso corretto di indicizzazione, partizionamento orizzontale, ecc. Ecco uno schema di documenti DB parziale per i libri collezioni:

...
sku: SKU,
pid: Product ID,
title: String,
auth: String,
pub: String,
isbn: ISBN,
edition: Int,
price: Float,
rating: Float,
cats: [String, String ...],
tags: [String, String ...],
...

Registri anche le transazioni in una raccolta chiamata txns che potrebbe assomigliare a:

txnid: TxnID,
cid: CustomerID,
amnt: Float,
curr: Currency,
sku: [sku1, sku2, ...],
time: TimeStamp,
...

E una raccolta di viste chiamata viste:

time: TimeStamp, # daily aggregated
cid: CustomerID,
sku: [sku1, sku2, ...],
...

Ovviamente, questo è un esempio molto semplificato che fa ipotesi generali. Il nostro intento è mostrare un esempio di set Redis in uno scenario (quasi) reale.

Ok, quindi ora tu, come gestore del negozio, desideri uno strumento Visual Profiler per analizzare le relazioni e il comportamento dei clienti in diverse categorie. Ad esempio:

  • Qual ​​è la categoria più popolare?
  • Le persone che guardano o acquistano fantascienza guardano anche alla saggistica?

Vuoi essere in grado di farlo in tempo reale, ovvero l'interfaccia utente del profiler segnerà caselle, pulsanti che ti consentono di modificare i parametri e visualizzare i risultati (quasi) immediatamente.

L'esecuzione di tali operazioni su MongoDB comporterà l'esecuzione di query piuttosto complesse per unire varie categorie, tag e altri dati che potrebbero interessarti. Con un set di lavoro che non si adatta alla memoria, queste non sarebbero le operazioni più veloci. Ad esempio:

  • Trovare tutti i libri venduti oggi che erano di narrativa, ma non di fantascienza, comporterà l'interrogazione del txn raccolta delle transazioni odierne. Quindi, scorrere gli SKU per raccogliere le loro categorie e quindi eseguire operazioni $in/$nin.

Vediamo come verrebbe gestito inserendo Redis nel mix. Alla fine di ogni giornata, i lavori pianificati giornalieri possono essere eseguiti su queste raccolte MongoDB per creare set Redis. Il tipo di set che desideri creare dipenderà dal tipo di filtri che desideri supportare sul tuo frontend. Ad esempio, supponiamo che desideri supportare le query relative alla categoria, vorremo creare set come:

cat:type:catID
cat:sku:fiction
cat:sku:nonfiction
cat:sku:scfiction
cat:sku:history
cat:sku:milhistory
cat:sku:military
...
cat:cid:fiction
cat:cid:nonfiction
cat:cid:scfiction
cat:cid:history
cat:cid:milhistory
cat:cid:military
...

I set cat:sku:* conterranno SKU di libri venduti/visti oggi in quella categoria. Allo stesso modo, cat:cid:* conterrà il CID dei clienti che hanno acquistato/venduto libri in quella categoria. Un esempio di domande a cui possiamo rispondere con questi set sono:

  • Clienti (o n. di clienti) che hanno visualizzato/acquistato libri di narrativa (categoria singola) oggi:smembers cat:cid:fiction
  • Clienti che hanno visualizzato/acquistato Storia ma non Storia militare oggi:sdiff cat:cid:history cat:cid:milhistory
  • (Numero di) libri venduti oggi che erano di fantascienza e militare, ovvero fantascienza militare:sinter cat:sku:scfiction cat:sku:military
  • Qualsiasi numero di operazioni di unione, intersezione e differenza che ti interessano.

Questo ci offre capacità di interrogazione molto potenti. Aggiungiamo più set! Supponiamo che creiamo set aggiuntivi in ​​base alle valutazioni dei libri. Ad esempio:

rat:sku:5str: Set of books with ratings > 4.5
rat:sku:4str: Set of books with ratings > 3.5 && <= 4.5
rat:sku:3str: ...
rat:sku:2str: ...
...
rat:cid:5str: Set of customer who bought books with ratings as mentioned above.
rat:cid:4str: ...
..

Dotato di questi set, ora puoi scoprire rapidamente cose come:

  • Libri di narrativa a 4 stelle e oltre acquistati oggi:  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:fiction
  • Cliente che ha acquistato libri a 3 stelle e oltre nella storia:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:history rat:cid:5strabv

Ora, supponiamo che tu voglia inviare un buono sconto a tutti i tuoi clienti che hanno acquistato oggi un libro di astrologia con una valutazione di 2 o inferiore (come scusa per la brutta esperienza di dover leggere quel libro!). Puoi esportare quell'elenco di ID cliente s e invialo alla tua applicazione di posta elettronica. Allo stesso modo, puoi creare set per altre cose che potresti voler esporre come filtri nel tuo Visual Profiler come tag, fasce di prezzo, ecc.

I vantaggi dell'utilizzo dei Redis Set sono evidenti qui. L'archivio in memoria porterà a un accesso davvero veloce in modo che il front-end sia scattante. Inoltre, le operazioni sui set Redis sono a tempo costante o lineari.

Conclusione

In questo post, abbiamo introdotto con esempi una delle strutture dati Redis più utili:gli insiemi. Ecco alcuni dei nostri altri post nella serie di strutture dati Redis:

  • Hash Redis
  • Bitmap Redis
  • Set Redis
  • Insiemi ordinati Redis