sql >> Database >  >> NoSQL >> Redis

Maak kennis met de Redis-database:itereren over sleutels

Een van de dingen die gebruikers die bekend zijn met andere databases vaak in verwarring brengen wanneer ze Redis proberen, is het gebrek aan zichtbaarheid in de database:er is geen set tabellen of verzamelingen om kijk, gewoon een eenvoudige, platte sleutelruimte die (potentieel) miljoenen sleutels zou kunnen hebben. De mogelijkheid om goedkoop over deze sleutelruimte te itereren wordt dus erg belangrijk om vertrouwd te raken met de database-inhoud.

Itereren over de Redis-sleutelruimte heeft ook andere belangrijke use-cases die in je opkomen zijn:

  • vuilnisophaling of sleutels opruimen die overeenkomen met een bepaald patroon
  • gegevensverplaatsing en schemawijzigingen of het verplaatsen van een bepaalde set sleutels naar een andere gegevensstructuur
  • foutopsporing, gegevenssampling, gegevenscorrecties of het vinden en repareren van alle sleutels die door een recente wijziging zijn verknoeid

In dit bericht gaan we dieper in op verschillende belangrijke iteratie-opties voor ruimte die beschikbaar zijn in Redis.

O(N) Iterators:SLEUTELS

De opdracht Redis KEYS retourneert alle sleutels in de database die overeenkomen met een patroon (of alle sleutels in de sleutelruimte). Soortgelijke opdrachten voor het ophalen van alle velden die in een hash zijn opgeslagen, zijn HGETALL en voor het ophalen van de leden van een SMEMBERS. De sleutels in Redis zelf worden opgeslagen in een woordenboek (ook wel een hash-tabel genoemd). Het KEYS-commando werkt door dit woordenboek te herhalen en alles dat overeenkomt met het patroon als een enkel array-antwoord te verzenden. De andere commando's werken op dezelfde manier.

De prestatie van een dergelijke bewerking hangt af van de grootte van de verzameling, d.w.z. O(N). Het gebruik van KEYS wordt daarom sterk afgeraden in productieomgevingen met een groot aantal sleutels. Redis is single-threaded en wordt tijdens deze iteratie geblokkeerd, waardoor andere bewerkingen worden geblokkeerd. KEYS mag dus alleen worden gebruikt voor foutopsporing en andere speciale gelegenheden waarbij prestaties geen probleem zijn (zoals wanneer de database offline is gehaald om een ​​gegevenscorrectie toe te passen). Het andere belangrijke om te onthouden over dit algoritme is dat het alle overeenkomende sleutels samen als één enkele reactie verzendt. Dit kan erg handig zijn als de sleutelruimte klein is, maar er ontstaan ​​meerdere problemen op een grote sleutelruimte. KEYS is echter een favoriet commando onder ontwikkelaars in hun eigen ontwikkelomgevingen.

KEYS in actie:

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"

Cursorgebaseerde iterators:SCAN

De SCAN en zijn zustercommando's, SSCAN (voor sets), HSCAN (voor hashes) en ZSCAN (voor gesorteerde sets) bieden de cursorgebaseerde benadering voor iteratie over Redis-gegevensstructuren. Ze zijn beschikbaar in Redis sinds 2.8.0.

Sleutels worden geretourneerd in incrementele iteraties met constante tijdgarantie voor elke iteratie. Een cursor (in dit geval een geheel getal) wordt geretourneerd wanneer de iteraties worden geïnitialiseerd en een bijgewerkte cursor wordt geretourneerd en elke iteratie. Een iteratiecyclus begint wanneer de cursor is ingesteld op 0 in het SCAN-verzoek en eindigt wanneer de cursor die door de server wordt geretourneerd 0 is. Vanwege nuances van de Redis-architectuur en de implementatie van het cursoralgoritme zijn hier enkele eigenaardigheden van deze benadering:

  • Een volledige iteratie haalt altijd alle elementen op die aanwezig waren in de collectie vanaf het begin tot het einde van een volledige iteratie.
  • Een volledige iteratie retourneert nooit een element dat NIET aanwezig was in de collectie vanaf het begin tot het einde van een volledige iteratie.
  • Een bepaald element kan meerdere keren worden geretourneerd. Het is aan de applicatie om het geval van dubbele elementen af ​​te handelen
  • Elementen die tijdens een volledige iteratie niet constant in de collectie aanwezig waren, kunnen worden geretourneerd of niet:het is niet gedefinieerd.
  • Een aantal elementen dat tijdens elke telling wordt geretourneerd, varieert en kan ook 0 zijn. De iteratie is echter pas voltooid als de server de cursorwaarde 0 retourneert.
  • De COUNT optie kan worden gebruikt om het aantal elementen dat in elke iteratie wordt geretourneerd te beperken. De standaardwaarde is 10. Het wordt echter slechts als een suggestie beschouwd en wordt niet in alle gevallen afgedwongen. De COUNT-waarde kan tijdens elke iteratieaanroep worden gewijzigd.
  • De MATCH optie staat het specificeren van patronen toe zoals het KEYS-commando toestaat.
  • De cursorimplementatie is volledig stateloos aan de serverzijde. Dat maakt het mogelijk (potentieel) oneindige iteraties parallel te starten. Er zijn ook geen vereisten om ervoor te zorgen dat een iteratie tot het einde doorgaat en op elk moment kan worden gestopt.

Ondanks zijn eigenaardigheden, is SCAN een zeer nuttig commando en het juiste commando om te kiezen voor iteraties van sleutelruimten voor de meeste gevallen.

SCAN is een zeer nuttige opdracht en de juiste opdracht om te kiezen voor iteraties van sleutelruimten in #RedisClick To Tweet

SCAN in actie

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"

Onder de motorkap

Het algoritme dat SCAN (en zijn zustercommando's) gebruiken om doorheen te scannen, is intrigerend en leidt tot enkele van de kenmerken van het commando dat we hierboven beschreven. Antirez beschreef het op hoog niveau in zijn blogpost en het wordt (iets beter) uitgelegd in de comments boven de implementatie (functie dictScan). Door het in details te beschrijven, wordt dit bericht te lang, dus ik zal voldoende beschrijving geven om de implicaties ervan duidelijk te maken.

  • De meeste Redis-gegevensstructuren worden intern weergegeven als woordenboeken (ten minste gedeeltelijk in het geval van gesorteerde sets). Ze zijn geïmplementeerd als power-of-two hash-tabellen met kettingen voor botsingen. De uitdaging bij het schrijven van een op cursor gebaseerd iteratief algoritme is om te kunnen omgaan met het groeien en krimpen van de hash zonder de Redis-principes van eenvoud (van de API) en snelheid op te offeren.
  • SCAN scant in feite elke iteratie een aantal hash-buckets en retourneert de elementen die overeenkomen met het patroon daarin. Omdat het alleen naar een vaste lijst met buckets kijkt, kan het zijn dat iteraties soms helemaal geen waarden retourneren.
  • De cursor die wordt geretourneerd, is in feite een offset in de hashtabel die wordt herhaald. Het behandelt het groeien en krimpen van hashtabellen (d.w.z. opnieuw hashen) door slimme manipulatie van bits van een hoger niveau van de offset, terwijl de offset samen met de eigenschappen van de hashtabel wordt verhoogd. Implicaties van deze aanpak zijn dat nieuwe elementen die tijdens de iteratie zijn toegevoegd al dan niet worden geretourneerd. De cursor zelf zou echter niet opnieuw hoeven te starten bij een wijziging in de grootte van de hashtabel.
  • Een bepaalde bucket moet slechts één keer worden bezocht en alle sleutels moeten in één keer worden geretourneerd. Dit is opnieuw om ervoor te zorgen dat de grootte van de hash (d.w.z. opnieuw hashen) de voortgang van de iteratie niet bemoeilijkt. Dit leidt er echter toe dat het argument COUNT niet strikt afdwingbaar is.
  • Aangezien de bovenstaande benadering volledig stateless is aan de serverzijde, betekent dit in feite dat iteraties kunnen worden gestopt of dat een groot aantal iteraties parallel kan worden gestart zonder dat er meer geheugen wordt gebruikt.

Samenvatting

Op een hoog niveau zijn er twee keuzes beschikbaar om de Redis-sleutelruimte te herhalen:

  1. Gebruik KEYS wanneer prestaties geen probleem zijn of wanneer de sleutelruimte redelijk groot is.
  2. Gebruik op alle andere momenten SCAN.
Om de #Redis-sleutelruimte te herhalen, gebruikt u KEYS wanneer prestaties geen probleem zijn, anders gebruikt u SCANClick To Tweet

Wist je dat we nu hosting voor Redis™* ondersteunen? Krijg volledig beheerde hosting voor Redis™ in de veiligheid van uw eigen cloudaccount en maak gebruik van AWS/Azure-tegoeden voor uw Redis™-implementaties.


  1. Importeer csv-gegevens als array in mongodb met behulp van mongoimport

  2. MongoDB $dateToParts

  3. Hoe verwijder je in mongoDb een array-element door zijn index?

  4. Wat is het verschil tussen StackExchange.Redis en StackExchange.Redis.StrongName?