sql >> Databasteknik >  >> NoSQL >> Redis

Introduktion till Redis Data Structures:Sets

Redis (Remote Dictionary Server) är en omåttligt populär nyckel-värdelagring i minnet som också tillhandahåller valfri hållbarhet, partitionering, replikering och en mängd andra funktioner. Det är för närvarande den mest populära nyckel-värde-databasen och är känd för sin enkelhet, låga minnesyta och en låg inlärningskurva. Redis kallas också för en datastrukturserver och har stöd för atomoperationer på datastrukturer som hash, listor, uppsättningar, sorterade uppsättningar, bitmappar och hyperlogloggar. I det här inlägget kommer vi att titta på den inställda datatypen som tillhandahålls av Redis tillsammans med dess användning och verkliga användningsfall.

Redis Sets

Redis-uppsättningar är oordnade samlingar av strängar (en sträng är det grundläggande Redis-värdet som kan innehålla nästan vad som helst) som ger konstant tillägg, borttagning och medlemskapskontroller. Redis stöder också ganska snabba unions-, skärnings- och subtraktionsoperationer mellan set. Som förväntat tillåter den inte upprepade värden.

Här är några exempel på Redis-set i aktion från redis-cli . Här är en sammanfattning av nyckelrepresentationer i exemplet nedan:

  • users:all representerar en uppsättning av alla användare som är registrerade på en webbplats.
  • users:actv representerar aktiva användare.
  • users:inactv representerar inaktiva användare (användare som inte har besökt webbplatsen på ett tag).
# 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"

Andra viktiga uppsättningskommandon inkluderar:

  • SUNION – ställ in union
  • SPOP – ta bort ett element slumpmässigt
  • SREM – ta bort ett eller flera element

Den kompletta listan över uppsättningsrelaterade Redis-kommandon finns här.

Redis Internals

Redis lagrar internt set som ordböcker. Ordböcker i Redis är implementerade som hashtabeller som använder hashfunktionen MurmurHash2 och växer via inkrementell storleksändring. Hashkollisioner hanteras genom kedja. Uppsättningar har en speciell kodning för små uppsättningar när alla medlemmar i en uppsättning är i radix 10 i intervallet # av 64-bitars heltal med tecken som kallas IntSets. Detta är i huvudsak en sorterad matris av heltal. Sökningar inom arrayen utförs genom binär sökning. Uppenbarligen är denna implementering effektiv för mycket små uppsättningar. Storleken till vilken denna kodning används styrs av set-max-intset-entries konfigurationsparameter. Standardvärdet är 512. En bra beskrivning av interna datastrukturer som används av Redis finns här.

Redis-applikationer

Här är en liten lista över några av de möjliga Redis Set-applikationerna:

  • Som en uppsättning kan den användas för att spåra unika objekt:
    • Alla unika IP-adresser som besöker din webbplats.
    • Alla unika jobbinstanser för närvarande i ett visst tillstånd osv.
  • Återigen, som en uppsättning, kan den användas för att beteckna som "tillhör" eller liknande relation:
    • Alla SKU:er som tillhör en viss kategori.
    • Alla objekt med en viss tagg, etc.
  • Mängder kan endast användas för att kombinera relationer, d.v.s. union/skärning/subtraktion av mängder:
    • Alla SKU:er som tillhör kategorin t-shirts, men inte en underkategori av pikéhalsar.

Låt oss ta ett exempel från verkligheten och utforska uppsättningsrelaterade användningsfall ytterligare.

Visuell profilering för din e-bokbutik

Låt oss säga att du är ägare till en mycket stor onlinebokbutik som listar miljontals titlar. Din primära databas är MongoDB och den fungerar ganska bra för de flesta av dina användningsfall med korrekt användning av indexering, sharding, etc. Här är ett partiellt DB-dokumentschema för böckerna samlingar:

...
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 ...],
...

Du registrerar även transaktioner i en samling som heter txns som kan se ut så här:

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

Och en samling för vyer som heter vyer:

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

Det här är uppenbarligen ett mycket förenklat exempel som gör breda antaganden. Vår avsikt är att visa ett Redis-exempel i ett (nästan) verkligt scenario.

Ok, så nu vill du som butikschef ha ett Visual Profiler-verktyg för att analysera relationer och kundbeteende i olika kategorier. Till exempel:

  • Vilken är den populäraste kategorin?
  • Kankar folk som tittar på eller köper science fiction också på facklitteratur?

Du vill kunna göra detta i realtid, d.v.s. profilerarens användargränssnitt kommer att markera rutor, knappar som låter dig ändra parametrar och se resultat (nästan) omedelbart.

Att utföra sådana operationer på MongoDB kommer att innebära att du utför ganska inblandade frågor för att gå med i olika kategorier, taggar och annan data som du kanske bryr dig om. Med en fungerande uppsättning som inte passar i minnet skulle dessa inte vara de snabbaste operationerna. Till exempel:

  • Att hitta alla böcker som säljs idag och som var fiktion, men inte science fiction kommer att innebära att du söker efter txn insamling av dagens transaktioner. Itererar sedan över SKU:erna för att samla in deras kategorier och gör sedan $in/$nin operationer.

Låt oss se hur detta skulle hanteras genom att ta med Redis i mixen. I slutet av varje dag kan dagliga schemalagda jobb köra över dessa MongoDB-samlingar för att skapa Redis-uppsättningar. Vilken typ av uppsättningar du vill skapa beror på vilken typ av filter du vill stödja på din frontend. Säg till exempel att du vill stödja kategorirelaterade frågor, vi vill skapa uppsättningar som:

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
...

Seten cat:sku:* kommer att innehålla SKU:er för böcker som säljs/visas idag i den kategorin. På liknande sätt kommer cat:cid:* att innehålla kund-ID för kunder som har köpt/sålt böcker i den kategorin. Ett exempel på frågor vi kan besvara med dessa uppsättningar är:

  • Kunder (eller antal kunder) som har tittat på/köpt skönlitteratur (en kategori) böcker idag:smembers cat:cid:fiction
  • Kunder som har tittat på/köpt historia men inte militärhistoria idag:sdiff cat:cid:history cat:cid:milhistory
  • (Antal) Böcker sålda idag som var Science Fiction och Military, dvs. militär science fiction:sinter cat:sku:scfiction cat:sku:military
  • Valfritt antal sådana förenings-, korsnings- och skillnadsoperationer som du bryr dig om.

Detta i sig ger oss mycket kraftfulla frågemöjligheter. Låt oss lägga till fler set! Säg att vi skapar ytterligare uppsättningar baserat på bokbetyg. Till exempel:

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: ...
..

Utrustad med dessa uppsättningar kan du nu snabbt ta reda på saker som:

  • 4-stjärniga eller högre skönlitterära böcker köpta idag:  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:fiktion
  • Kund som köpte 3-stjärniga böcker och högre i historien:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:history rat:cid:5strabv

Låt oss nu säga att du vill skicka en rabattkupong till alla dina kunder som köpte en Astrologibok idag med betyget 2 eller lägre (som en ursäkt för den dåliga upplevelsen att behöva läsa den boken!). Du kan exportera listan med Kund-ID s ut och skicka den till din e-postapplikation. På samma sätt kan du skapa uppsättningar för andra saker som du kanske vill exponera som filter i din Visual Profiler som taggar, prisklasser, etc.

Fördelarna med att använda Redis Sets är uppenbara här. In-memory-butiken kommer att leda till riktigt snabb åtkomst så att fronten känns knäpp. Dessutom är Redis set operationer antingen konstant tid eller linjär.

Slutsats

I det här inlägget introducerade vi med exempel en av de mest användbara Redis Data Structures:Sets. Här är några av våra andra inlägg i serien Redis datastrukturer:

  • Redis Hashes
  • Redis bitmappar
  • Redis-set
  • Redised Sorterade uppsättningar


  1. Rate-Limit an API (spring MVC)

  2. MongoDB - Fråga mellan ett tidsintervall på timmar

  3. $nin med $expr

  4. MongoDB frågar prestanda för över 5 miljoner poster