Nå, dette forventes af enhver effektiv datalagring:ordene skal indekseres i hukommelsen i en dynamisk datastruktur af celler forbundet med pointere. Størrelsen af strukturens metadata, pointere og hukommelsesallokator intern fragmentering er grunden til, at data tager meget mere hukommelse end en tilsvarende flad fil.
Et Redis-sæt implementeres som en hash-tabel. Dette inkluderer:
- en række af pointere, der vokser geometrisk (to potenser)
- et andet array kan være påkrævet, når inkrementel rehashing er aktiv
- enkelt-linkede listeceller, der repræsenterer posterne i hash-tabellen (3 pointere, 24 bytes pr. post)
- Redis-objektindpakninger (én pr. værdi) (16 bytes pr. indtastning)
- faktiske data selv (hver af dem foranstillet med 8 bytes for størrelse og kapacitet)
Alle ovenstående størrelser er givet for 64 bit implementeringen. Når der tages højde for hukommelsesallokatorens overhead, resulterer det i, at Redis tager mindst 64 bytes pr. sæt element (udover dataene) for en nyere version af Redis ved hjælp af jemalloc-allokatoren (>=2.4)
Redis leverer hukommelsesoptimeringer for nogle datatyper, men de dækker ikke sæt af strenge. Hvis du virkelig har brug for at optimere hukommelsesforbruget af sæt, er der dog tricks, du kan bruge. Jeg ville ikke gøre dette for kun 160 MB RAM, men hvis du har større data, er her, hvad du kan gøre.
Hvis du ikke har brug for forenings-, skærings-, forskelsevnerne for sæt, kan du gemme dine ord i hash-objekter. Fordelen er, at hash-objekter kan optimeres automatisk af Redis ved hjælp af zipmap, hvis de er små nok. Zipmap-mekanismen er blevet erstattet af ziplist i Redis>=2.6, men ideen er den samme:Brug af en serialiseret datastruktur, som kan passe ind i CPU-cachene for at få både ydeevne og et kompakt hukommelsesfodaftryk.
For at sikre, at hash-objekterne er små nok, kan dataene distribueres i henhold til en hash-mekanisme. Hvis du antager, at du skal gemme 1 mio. varer, kan tilføjelse af et ord implementeres på følgende måde:
- hash it modulo 10000 (udført på klientsiden)
- HMSET-ord:[hashnum] [ord] 1
I stedet for at gemme:
words => set{ hi, hello, greetings, howdy, bonjour, salut, ... }
du kan gemme:
words:H1 => map{ hi:1, greetings:1, bonjour:1, ... }
words:H2 => map{ hello:1, howdy:1, salut:1, ... }
...
For at hente eller kontrollere eksistensen af et ord, er det det samme (hash det og brug HGET eller HEXISTS).
Med denne strategi kan der foretages en betydelig hukommelsesbesparelse, forudsat at moduloen for hashen er valgt i henhold til zipmap-konfigurationen (eller ziplist for Redis>=2.6):
# Hashes are encoded in a special way (much more memory efficient) when they
# have at max a given number of elements, and the biggest element does not
# exceed a given threshold. You can configure this limits with the following
# configuration directives.
hash-max-zipmap-entries 512
hash-max-zipmap-value 64
Pas på:Navnet på disse parametre er ændret med Redis>=2.6.
Her betyder modulo 10000 for 1M genstande 100 genstande pr. hash-objekter, hvilket vil garantere, at de alle er gemt som zipmaps/ziplister.