Redis
 sql >> база данни >  >> NoSQL >> Redis

Въведение в Redis структури от данни:хешове

Хешовете на Redis са (достатъчно интуитивно!) хешове, които съпоставят имената на низове със стойности на низове. По същество те са наречени контейнери с уникални полета и техните стойности. Те са идеалният начин да представите обект като структура от данни на Redis. Както се очаква, те осигуряват постоянно време основни операции като get, set, exists и т.н. Предоставени са и куп разширени операции. Пълният списък с хеш команди е тук.

Нека го разгледаме от redis-cli .

# hmset key field value [field value ...] :  Insert elements in a hash. O(N), N is # of field being set
127.0.0.1:6379> hmset std:101 name "John Smith" dob "01-01-2000" gender M active 0 cgpa 2.9
OK

# hgetall key : key all keys and values in the hash. O(N), N is size of hash
127.0.0.1:6379> hgetall std:101
 1) "name"
 2) "John Smith"
 3) "dob"
 4) "01-01-2000"
 5) "gender"
 6) "M"
 7) "active"
 8) "0"
 9) "cgpa"
10) "2.9"
127.0.0.1:6379> hmset std:102 name "Jane" name "Ann"
OK
# If duplicates are found, only the last set is valid
127.0.0.1:6379> hgetall std:102
1) "name"
2) "Ann"

# hexists key field: does field exist in the hash with key. O(1)
127.0.0.1:6379> hexists std:102 cgpa
(integer) 0

# hincrby key field increment: Increment the integer field by increment. O(1)
127.0.0.1:6379> hincrby std:101 active 1
(integer) 1

# hget key field : the value for field in the hash stored at key. O(1)
127.0.0.1:6379> hget std:101 active
1) "1"
# If field doesn't exist, hincrby sets it to 0 and then applies increment
127.0.0.1:6379> hincrby std:102 active 2
(integer) 2

# hmget key field [field ...]: the values of the fields requested for the hash with key. O(N), N is # of keys requested
127.0.0.1:6379> hmget std:102 active
1) "2"

# hincrbyfloat key field increment: Increment the float value in field by increment. O(1) 
127.0.0.1:6379> HINCRBYFLOAT std:101 cgpa 1.0
"3.9"

# HSETNX key field value: set field to value if not alread set. O(1)
127.0.0.1:6379> hsetnx std:102 cgpa 4.0
(integer) 1
127.0.0.1:6379> hget std:102 cgpa
"4.0"

# hlen key: number of fields in the hash. O(1)
127.0.0.1:6379> hlen std:101
(integer) 5

# hkeys key : all fields in the hash. O(N), N is size of hash
127.0.0.1:6379> hkeys std:101
1) "name"
2) "dob"
3) "gender"
4) "active"
5) "cgpa"

Както очаквахме от нашия хостинг за Redis™* като сървър за структура на данни, виждаме, че Redis предоставя доста полезни и разширени операции с хешове.

Вътрешни елементи

Подобно на наборите на Redis, хешовете на Redis също се реализират като  речници. Речниците в Redis се изпълняват като хеш таблици, които използват хеш функцията MurmurHash2 и се увеличават чрез инкрементално преоразмеряване. Хеш колизиите се обработват чрез верижно свързване. Повече подробности можете да намерите в реализацията на Redis на речника на dict.c.
Както при наборите, има оптимизация на съхранението, направена за по-малки хешове. Тази структура от данни се нарича ziplist (хешовете са оптимизирани с помощта на различна структура от данни, наречена zipmap преди Redis 2.6) в реализацията на Redis. По същество това е специално кодиран двусвързан списък, който е оптимизиран за спестяване на памет. Данните, както и указателите се съхраняват на линия. Ziplist се използва и за оптимизиране на съхранението на по-малки сортирани набори и списъци. Хеш, когато е изравнен в такъв списък, изглежда нещо като [ключ1, стойност1, ключ2, стойност2, ...]. Как това е по-ефективно от обикновените ключове? Хешовете с няколко ключа могат да бъдат опаковани умело в тази структура като линеен масив (т.е. ziplist), като същевременно се гарантира амортизирана O(1) производителност за получаване и задаване. Очевидно това не може да продължи, тъй като хеш полетата се увеличават. Тъй като хешът нараства, той се преобразува в стандартната речникова структура, за да се поддържа O(1) производителност и спестяването на пространство се губи. Конфигурационните параметри на Redis, контролиращи тази трансформация, са:

  • list-max-ziplist-entries по подразбиране (512):Промяна на стандартно представяне, ако хешът нарасне по-голям от това ограничение.
  • list-max-ziplist-value по подразбиране (64):Промяна на стандартно представяне, ако най-големият елемент в хеша стане по-голям от това ограничение.

Повече подробности могат да бъдат разбрани от кода и коментарите в реализацията, намиращи се тук. Спестяванията на памет от използването на тази специална оптимизация са значителни. Ще говорим за повече подробности в следващия раздел.

Оптимизация на паметта

Една от добре познатите препоръки за спестяване на памет, докато използвате Redis, е да използвате хешове вместо обикновени низове. Това е важен случай на използване за използване на силата на хешовете на Redis в приложения от реалния свят. От официалната документация на Redis за оптимизирането на паметта:

Използвайте хешове, когато е възможно

Малките хешове са кодирани в много малко пространство, така че трябва да опитате да представите данните си с помощта на хешове всеки път, когато е възможно. Например, ако имате обекти, представляващи потребители в уеб приложение, вместо да използвате различни ключове за име, фамилия, имейл, парола, използвайте един хеш с всички задължителни полета.

След това тази публикация предлага един начин за картографиране на диапазон от обекти в набор от хешове, за да се възползвате от спестяванията на паметта. Instagram, в много популярна публикация в блог, описва използването на подобна техника, която им помогна да постигнат порядък на потенциални спестявания. Друг блог, който се опитва да измери ползите от оптимизацията е този.

Приложения

  • Хешовете на Redis са естествено подходящи за съхранение на обекти:сесии, потребители, посетители и т.н. Това го прави една от ключовите структури от данни, предоставени от Redis.
  • В своята оптимизирана за паметта форма, тя е отличен избор за кеширане на големи количества данни.

Съхранение на адреси на обекти

Тъй като оптимизацията на паметта е важен случай на използване на хешовете, нека обсъдим пример, подобен на внедряването в Instagram, за да покажем как да използвате функциите за спестяване на памет на хешовете на Redis. Да кажем, че имаме огромно внедряване на хранилище с адресиране на съдържание (CAS) със стотици милиони съхранявани обекти. Местоположението на всеки обект е хеш низ. Възнамеряваме да разработим система за търсене, за да разберем местоположението на обекта, като се има предвид неговият идентификатор. Типичният начин да направите това в Redis е да използвате низ.

set object:14590860 "007f80f0a62408..."
set object:11678 "009f80abcd0a60..."
...

Този подход работи добре. Въпреки това, тъй като броят на обектите, които имаме, е огромен, в крайна сметка ще се нуждаем от много памет за Redis. Искаме да се справим по-добре. Нека вземем оптимизирания за паметта хеш подход към този проблем. Ще трябва да изберем правилните стойности за list-max-ziplist-entries и list-max-ziplist-value . Правилната стойност за list-max-ziplist-value е каквато може да бъде максималната дължина на хеш низа на адреса за съхранение. Стойността на list-max-ziplist-entries трябва да се поддържа достатъчно нисък и ще зависи от броя на общите хеш кофи, които искаме да създадем. Най-добре ще бъде установено емпирично. За напр. за 100 милиона обекта бихме могли да изберем да използваме 100k хешове. Максималните записи в този случай ще бъдат 100m / 100k =1000. Логиката на приложението да реши в кой хеш влиза адресът за съхранение на обект може да бъде:разделете идентификатора на обекта на 100k и изхвърлете остатъка. Така обект ID 14590860 ще влезе в хеш (14590860/100k) =145 т.е.


hset object:145 14590860 "007f80f0a62408..."
hget object:145 14590860
> "007f80f0a62408..."

Тази реализация не само ще бъде много по-лека за паметта, но също така трябва да осигури добро местоположение на кеша.

Ето и другите ни публикации в поредицата за структура на данните на Redis.

  • Набори на Redis
  • Растрови изображения на Redis
  • Сортирани набори на Redis

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Получавам грешка Клас 'Predis\Client' не е намерен в Laravel 5.2

  2. Може ли celery celerybeat да използва планировчик на база данни без Django?

  3. Как да проверя дали redis работи, преди да стартирам flask (и да го стартирам, ако не е)?

  4. node redis, променливите се споделят между клиентите?

  5. Използване на Redis Sets