sql >> Database >  >> NoSQL >> Redis

Inleiding tot Redis-gegevensstructuren:sets

Redis (Remote Dictionary Server) is een immens populaire in-memory key-value store die ook voorziet in optionele duurzaamheid, partitionering, replicatie en tal van andere functies. Het is momenteel de meest populaire sleutel-waardedatabase en staat bekend om zijn eenvoud, lage geheugenvoetafdruk en een lage leercurve. Redis wordt ook wel een datastructuurserver genoemd en biedt ondersteuning voor atomaire bewerkingen op datastructuren zoals hashes, lijsten, sets, gesorteerde sets, bitmaps en hyperloglogs. In dit bericht zullen we kijken naar het ingestelde gegevenstype dat door Redis wordt geleverd, samen met het gebruik en de praktijkgevallen.

Redis-sets

Redis-sets zijn ongeordende verzamelingen tekenreeksen (een tekenreeks is de basiswaarde van Redis die bijna alles kan bevatten) die constante tijdtoevoeging, verwijdering en lidmaatschapscontroles biedt. Redis ondersteunt ook redelijk snelle unie-, intersectie- en aftrekbewerkingen tussen sets. Zoals verwacht, staat het geen herhaalde waarden toe.

Hier zijn enkele voorbeelden van Redis-sets in actie uit de redis-cli . Hier is een samenvatting van de belangrijkste representaties in het onderstaande voorbeeld:

  • users:all vertegenwoordigt een verzameling van alle gebruikers die op een website zijn geregistreerd.
  • users:actv staat voor actieve gebruikers.
  • users:inactv staat voor inactieve gebruikers (gebruikers die de site al een tijdje niet hebben bezocht).
# 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"

Andere belangrijke set-commando's zijn:

  • SUNION – unie instellen
  • SPOP – verwijder willekeurig een element
  • SREM – verwijder een of meer elementen

De volledige lijst met set-gerelateerde Redis-commando's vindt u hier.

Redis-binnenwerk

Redis slaat intern sets op als woordenboeken. Woordenboeken in Redis worden geïmplementeerd als hash-tabellen die de hash-functie MurmurHash2 gebruiken en groeien via incrementele resizing. Hash-botsingen worden afgehandeld door middel van chaining. Sets hebben een speciale codering voor kleine sets wanneer alle leden van een set in radix 10 staan ​​in het bereik # van 64-bits gehele getallen met teken, IntSets genoemd. Dit is in wezen een gesorteerde reeks gehele getallen. Zoekopdrachten binnen de array worden uitgevoerd via binair zoeken. Het is duidelijk dat deze implementatie efficiënt is voor zeer kleine sets. Tot welke grootte deze codering wordt gebruikt, wordt bepaald door set-max-intset-entries configuratieparameter. De standaardwaarde is 512. Een goede beschrijving van de interne gegevensstructuren die door Redis worden gebruikt, vindt u hier.

Redis-apps

Hier is een kleine lijst van enkele van de mogelijke Redis Set-applicaties:

  • Als set kan het worden gebruikt om unieke items bij te houden:
    • Alle unieke IP-adressen die uw site bezoeken.
    • Alle unieke baneninstanties die zich momenteel in een bepaalde staat bevinden, enz.
  • Nogmaals, als een set, kan het worden gebruikt om aan te duiden als "behoort tot" of een vergelijkbare relatie:
    • Alle SKU's die tot een bepaalde categorie behoren.
    • Alle objecten met een bepaalde tag, enz.
  • Sets kunnen alleen worden gebruikt om relaties te combineren, d.w.z. vereniging/kruising/aftrekking van sets:
    • Alle SKU's die tot de categorie T-shirts behoren, maar geen subcategorie van polohalzen.

Laten we een voorbeeld uit de praktijk pakken en set-gerelateerde use-cases verder verkennen.

Visuele profiler voor uw eBook Store

Stel dat u de eigenaar bent van een zeer grote online boekwinkel met miljoenen titels. Uw primaire database is MongoDB en deze presteert redelijk goed voor de meeste van uw gebruikssituaties met het juiste gebruik van indexering, sharding, enz. Hier is een gedeeltelijk DB-documentschema voor de boeken collecties:

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

U registreert ook transacties in een verzameling genaamd txns die eruit kan zien als:

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

En een verzameling voor weergaven genaamd weergaven:

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

Dit is duidelijk een sterk vereenvoudigd voorbeeld dat algemene aannames doet. Het is onze bedoeling om een ​​Redis-voorbeeld te laten zien in een (bijna) realistisch scenario.

Ok, dus nu wil je, als winkelmanager, een Visual Profiler-tool om de relaties en het klantgedrag in verschillende categorieën te analyseren. Bijvoorbeeld:

  • Wat is de meest populaire categorie?
  • Kijken mensen die sciencefiction bekijken of kopen ook naar non-fictie?

Je wilt dit in realtime kunnen doen, d.w.z. de gebruikersinterface van de profiler zal vakjes aanvinken, knoppen waarmee je parameters kunt wijzigen en resultaten (bijna) onmiddellijk kunt bekijken.

Het uitvoeren van dergelijke bewerkingen op MongoDB zal gepaard gaan met het uitvoeren van nogal ingewikkelde query's om verschillende categorieën, tags en andere gegevens samen te voegen die u misschien belangrijk vindt. Met een werkset die niet in het geheugen past, zouden dit niet de snelste bewerkingen zijn. Bijvoorbeeld:

  • Als je alle boeken wilt vinden die vandaag zijn verkocht en die wel fictie waren, maar geen sciencefiction, moet je de txn opvragen. verzameling van de transacties van vandaag. Vervolgens herhalen we de SKU's voor het verzamelen van hun categorieën en voeren vervolgens $in/$nin-bewerkingen uit.

Laten we eens kijken hoe dit aangepakt zou worden door Redis erbij te betrekken. Aan het einde van elke dag kunnen dagelijks geplande taken over deze MongoDB-verzamelingen lopen om Redis-sets te maken. Het soort sets dat u wilt maken, is afhankelijk van het soort filters dat u op uw frontend wilt ondersteunen. Stel dat u bijvoorbeeld categoriegerelateerde zoekopdrachten wilt ondersteunen, dan willen we sets maken zoals:

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

De cat:sku:* sets bevatten SKU's van boeken die vandaag in die categorie zijn verkocht/bekeken. Op dezelfde manier bevat cat:cid:* de CID van klanten die boeken in die categorie hebben gekocht/verkocht. Een voorbeeld van vragen die we met deze sets kunnen beantwoorden zijn:

  • Klanten (of # klanten) die vandaag fictieboeken (één categorie) hebben bekeken/gekocht:leden cat:cid:fiction
  • Klanten die vandaag Geschiedenis hebben bekeken/gekocht maar geen Militaire Geschiedenis:sdiff cat:cid:history cat:cid:milhistory
  • (Aantal) boeken die vandaag zijn verkocht, die sciencefiction en militair waren, d.w.z. militaire sciencefiction:sinter cat:sku:scfiction cat:sku:military
  • Een willekeurig aantal van dergelijke unie-, intersectie- en verschilbewerkingen waar u om geeft.

Dit geeft ons zelf zeer krachtige querymogelijkheden. Laten we meer sets toevoegen! Stel, we maken extra sets op basis van boekbeoordelingen. Bijvoorbeeld:

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

Uitgerust met deze sets, kun je nu snel dingen ontdekken zoals:

  • Fictieboeken met vier sterren en hoger die vandaag zijn gekocht:  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:fictie
  • Klant die boeken met drie sterren of hoger in de geschiedenis heeft gekocht:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:history rat:cid:5strabv

Stel nu dat u een kortingsbon wilt sturen naar al uw klanten die vandaag een astrologieboek hebben gekocht met een beoordeling van 2 of lager (als verontschuldiging voor de slechte ervaring om dat boek te moeten lezen!). U kunt die lijst met Klant-ID . exporteren s uit en stuur het naar uw e-mailtoepassing. Op dezelfde manier kunt u sets maken voor andere dingen die u als filters in uw Visual Profiler wilt weergeven, zoals tags, prijsklassen, enz.

De voordelen van het gebruik van Redis-sets zijn hier duidelijk. De in-memory store zal leiden tot echt snelle toegang, zodat de frontend pittig aanvoelt. Bovendien zijn de bewerkingen van Redis-sets ofwel constant in de tijd ofwel lineair.

Conclusie

In dit bericht hebben we met voorbeelden een van de handigste Redis-gegevensstructuren geïntroduceerd:sets. Hier zijn enkele van onze andere berichten in de serie Redis-gegevensstructuren:

  • Redis-hashes
  • Redis-bitmaps
  • Redis-sets
  • Redis gesorteerde sets


  1. MongoDB kan de gegevensmap niet vinden na het upgraden naar Mac OS 10.15 (Catalina)

  2. docker:MISCONF Redis is geconfigureerd om RDB-snapshots op te slaan

  3. Vind dubbele URL's in mongodb

  4. Mangoestschema:'uniek' wordt niet gerespecteerd