En af de ting, der ofte forvirrer brugere, der er fortrolige med andre databaser, når de prøver Redis, er manglen på synlighed i databasen:Der er ingen sæt tabeller eller samlinger til se, bare et almindeligt, fladt nøglerum, som (potentielt) kunne have millioner af nøgler. Evnen til at iterere billigt over dette nøglerum bliver derfor meget vigtigt for at sætte sig ind i databasens indhold.
Iteration over Redis-tastrummet har andre vigtige use cases, som også kommer til at tænke på:
- affaldsindsamling eller oprydningsnøgler, der matcher et bestemt mønster
- dataflytning og skemaændringer eller flytning af et bestemt sæt nøgler til en anden datastruktur
- fejlretning, datasampling, datarettelser eller at finde og rette alle nøgler, der blev ødelagt af en nylig ændring
I dette indlæg vil vi grave dybt ned i forskellige nøglemuligheder for gentagelse af mellemrum, der er tilgængelige i Redis.
O(N) Iteratorer:NØGLER
Kommandoen Redis KEYS returnerer alle nøglerne i databasen, der matcher et mønster (eller alle nøglerne i nøglerummet). Lignende kommandoer til at hente alle felter gemt i en hash er HGETALL og for alle at hente medlemmer af en SMEMBERS. Nøglerne i Redis selv er gemt i en ordbog (alias en hash-tabel). KEYS-kommandoen fungerer ved at iterere over denne ordbog og sende alt, der matcher mønsteret, ud som et enkelt Array-svar. De andre kommandoer fungerer på samme måde.
Udførelsen af en sådan operation afhænger af samlingens størrelse, dvs. O(N). Derfor frarådes brugen af NØGLER alvorligt i produktionsmiljøer med et stort antal nøgler. Redis er enkelt gevind, bliver blokeret under denne iteration og blokerer dermed andre operationer. NØGLER bør således kun bruges til fejlfinding og andre specielle lejligheder, hvor ydeevne ikke er et problem (som når databasen er blevet bragt offline for at anvende en datarettelse). Den anden vigtige ting at huske om denne algoritme er, at den sender alle de matchende nøgler sammen som et enkelt svar. Dette kan være yderst praktisk, når nøglerummet er lille, men vil skabe flere problemer på et stort nøglerum. KEYS er dog en favoritkommando blandt udviklere i deres egne dev-miljøer.
NØGLER i aktion:
127.0.0.1:6379[1]> MSET en 1 to 2 tre 3 fire 4OK# Alle tasterne127.0.0.1:6379[1]> tasterne *1) "fire"2) "tre"3) " to"4) "én"# taster, der begynder med bogstavet 't'127.0.0.1:6379[1]> taster t*1) "tre"2) "to"# taster, der har et 'ee' i sig127. 0.0.1:6379[1]> nøgler *ee*1) "tre"
Markørbaserede iteratorer:SCAN
SCAN og dets søsterkommandoer, SSCAN (for sæt), HSCAN (for hashes) og ZSCAN (for sorterede sæt) giver den markørbaserede tilgang til iteration over Redis-datastrukturer. De har været tilgængelige i Redis siden 2.8.0.
Nøgler returneres i trinvise iterationer med konstant tidsgaranti for hver iteration. En markør (et heltal er dette tilfælde) returneres, når iterationerne initialiseres, og en opdateret markør returneres og hver iteration. En iterationscyklus begynder, når markøren er sat til 0 i SCAN-anmodningen, og afsluttes, når markøren, der returneres af serveren, er 0. På grund af nuancerne i Redis-arkitekturen og markøralgoritmeimplementeringen er her nogle ejendommeligheder ved denne tilgang:
- En fuld iteration henter altid alle de elementer, der var til stede i samlingen fra begyndelsen til slutningen af en fuld iteration.
- En fuld iteration returnerer aldrig noget element, der IKKE var til stede i samlingen fra starten til slutningen af en fuld iteration.
- Et givet element kan returneres flere gange. Det er op til applikationen at håndtere tilfælde af duplikerede elementer
- Elementer, der ikke konstant var til stede i samlingen under en fuld iteration, kan returneres eller ej:det er udefineret.
- Et antal elementer, der returneres under hver optælling, varierer og kan også være 0. Gentagelsen er dog ikke færdig, før serveren returnerer markørværdien 0.
- COUNT mulighed kan bruges til at begrænse antallet af elementer, der returneres i hver iteration. Standardværdien er 10. Det betragtes dog kun som et forslag og håndhæves ikke i alle tilfælde. COUNT værdi kan ændres under hvert iterationskald.
- MATCH mulighed tillader specificering af mønstre, som kommandoen KEYS tillader.
- Markørimplementeringen er fuldstændig statsløs på serversiden. Det tillader (potentielt) uendelige iterationer at starte parallelt. Der er heller ingen krav til at sikre, at en iteration fortsætter til slutningen og kan stoppes når som helst.
På trods af dets særegenheder er SCAN en meget nyttig kommando og den rigtige kommando til at vælge til gentagelser af mellemrum i de fleste tilfælde.
SCAN er en meget nyttig kommando og den rigtige kommando at vælge til gentagelser af mellemrum i #RedisClick To TweetSCAN i aktion
127.0.0.1:6379[1]> flushdbOK127.0.0.1:6379[1]> nøgler *(tom liste eller sæt)127.0.0.1:6379[1]> debug udfylder 33OK127.0.0.1:6379[ 1]> scan 0 COUNT 51) "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 421) "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 1001) "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 hætten
Algorithmen, som SCAN (og dens søsterkommandoer) bruger til at scanne igennem, er spændende og fører til nogle af egenskaberne ved kommandoen, som vi beskrev ovenfor. Antirez beskrev det på et højt niveau i sit blogindlæg, og det er forklaret (lidt bedre) i kommentarerne over implementeringen (funktion dictScan). At beskrive det i detaljer vil gøre dette indlæg for langt, så jeg vil give tilstrækkelig beskrivelse til at gøre dets implikationer tydelige.
- De fleste Redis-datastrukturer er internt repræsenteret som ordbøger (i det mindste delvist i tilfælde af sorterede sæt). De er implementeret som power-of-to-størrelse hash-tabeller med kæde til kollisioner. Udfordringen ved at skrive en markørbaseret iterativ algoritme her er at være i stand til at håndtere vækst og formindskelse af hashen uden at ofre Redis-principperne om enkelhed (af API'et) og hastighed.
- SCAN scanner grundlæggende en masse hash-buckets hver iteration og returnerer de elementer, der matcher mønsteret i disse. Da det kun ser på en fast liste af buckets, vil nogle gange gentagelser muligvis ikke returnere nogen værdier overhovedet.
- Markøren, der returneres, er grundlæggende en forskydning i hash-tabellen, der gentages. Den beskæftiger sig med vækst og krympning af hashtabeller (dvs. rehashing) ved smart manipulation af bits på højere niveau af offset, mens forskydningen øges sammen med egenskaberne for hashtabellen. Implikationer fra denne tilgang er, at nye elementer tilføjet under iterationen kan eller måske ikke returneres. Markøren selv behøvede dog ikke at genstarte ved en ændring i størrelsen af hashtabellen.
- En given bøtte skal kun besøges én gang, og alle dens nøgler skal returneres på én gang. Dette er igen for at sikre, at ændring af hash-størrelse (dvs. rehashing) ikke komplicerer iterationsforløbet. Dette fører dog til, at COUNT-argumentet ikke kan håndhæves strengt.
- Da ovenstående tilgang er fuldstændig statsløs på serversiden, indebærer det dybest set, at iterationer kan stoppes eller et stort antal iterationer kan startes parallelt uden øget hukommelsesforbrug.
Oversigt
På et højt niveau er der to muligheder for at iterere over Redis-tastrummet:
- Brug NØGLER, når ydeevne ikke er et problem, eller når nøglerummet er rimeligt stort.
- Brug på alle andre tidspunkter SCAN.
Vidste du, at vi nu understøtter hosting til Redis™*? Få fuldt administreret hosting til Redis™ i sikkerheden på din egen cloudkonto, og udnyt AWS/Azure-kreditter til dine Redis™-implementeringer.