Е, това се очаква от всяко ефективно съхранение на данни:думите трябва да бъдат индексирани в паметта в динамична структура от данни от клетки, свързани с указатели. Размерът на структурните метаданни, указателите и вътрешната фрагментация на разпределителя на паметта е причината данните да заемат много повече памет от съответния плосък файл.
Наборът Redis се изпълнява като хеш таблица. Това включва:
- Масив от указатели, растящи геометрично (степени на две)
- може да се наложи втори масив, когато е активно инкрементално повторно хеширане
- единично свързани списъчни клетки, представляващи записите в хеш таблицата (3 указателя, 24 байта на запис)
- Обвивки на обекти Redis (по една на стойност) (16 байта на запис)
- самите действителни данни (всеки от тях е с префикс от 8 байта за размер и капацитет)
Всички горепосочени размери са дадени за 64-битовата реализация. Като се отчитат допълнителните разходи на разпределителя на паметта, това води до това, че Redis отнема най-малко 64 байта на елемент от комплекта (в допълнение към данните) за последна версия на Redis, използвайки jemalloc разпределителя (>=2.4)
Redis предоставя оптимизации на паметта за някои типове данни, но те не покриват набори от низове. Ако наистина трябва да оптимизирате консумацията на памет от набори, има трикове, които можете да използвате. Не бих направил това само за 160 MB RAM, но ако имате по-големи данни, ето какво можете да направите.
Ако не се нуждаете от възможности за обединение, пресичане, разлика на множества, тогава можете да съхранявате думите си в хеш обекти. Предимството е, че хеш обектите могат да бъдат оптимизирани автоматично от Redis с помощта на zipmap, ако са достатъчно малки. Механизмът на zipmap е заменен от ziplist в Redis>=2.6, но идеята е същата:използване на сериализирана структура от данни, която може да се побере в кеша на процесора, за да получите както производителност, така и компактен отпечатък на паметта.
За да се гарантира, че хеш обектите са достатъчно малки, данните могат да бъдат разпределени според някакъв механизъм за хеширане. Ако приемем, че трябва да съхранявате 1M артикула, добавянето на дума може да се реализира по следния начин:
- хеширайте го по модул 10000 (направено от страна на клиента)
- HMSET думи:[хашнум] [дума] 1
Вместо да съхранявате:
words => set{ hi, hello, greetings, howdy, bonjour, salut, ... }
можете да съхранявате:
words:H1 => map{ hi:1, greetings:1, bonjour:1, ... }
words:H2 => map{ hello:1, howdy:1, salut:1, ... }
...
За да извлечете или проверите съществуването на дума, тя е същата (хеширайте я и използвайте HGET или HEXISTS).
С тази стратегия може да се постигне значително спестяване на памет, при условие че модулът на хеша е избран според конфигурацията на zipmap (или ziplist за 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
Внимавайте:имената на тези параметри са се променили с Redis>=2.6.
Тук модул 10000 за 1M елемента означава 100 елемента на хеш обекти, което ще гарантира, че всички те се съхраняват като zipmaps/ziplists.