Статьи

Redis RAM Ramification — Часть I

[Эта статья была написана Итамаром Хабером]

«… как мы знаем, есть известные известные; есть вещи, которые мы знаем, мы знаем. Мы также знаем, что есть известные неизвестные; то есть мы знаем, что есть некоторые вещи, которые мы не знаем. Но есть также неизвестные неизвестные — те, кого мы не знаем, мы не знаем «.

Министр обороны США Дональд Рамсфелд, 2002

сколько оперативной памяти нужно Redis?

Если есть один наиболее часто повторяющийся вопрос о Redis, то это тот. Точно так же сложно ответить точно, потому что ответ зависит от очень многих факторов. В этом посте (и, скорее всего, в нескольких последующих, поскольку я склонен бродить, пока я бормотал и бормочу), я попытаюсь отобразить потребление памяти Redis. Хотя я не могу гарантировать окончательный ответ на все вопросы, я надеюсь, что это поможет:

  • Повторите то, что мы знаем об известных известных ( KK s)
  • Превращайте известные неизвестные ( KU ) в KK, когда это возможно, или, по крайней мере, в известные грубо понятые неизвестные ( KRUU )
  • Надеюсь, наткнуться на некоторых неизвестных ( UU ), и превратить их в KUs, KRUUs или даже KKs!

Примечание: вы можете отслеживать мои успехи в этой серии, подписавшись на  канал RSS . Вы также можете зарегистрироваться в  Redis Watch  и получать еженедельные обновления на свой почтовый ящик. Наконец, но только если вы готовы,  подпишитесь на нас  в Твиттере в режиме реального времени.

Таким образом, Redis является частью программного обеспечения, и для его работы требуется оперативная память. Но Redis — это не просто программное обеспечение, это база данных в памяти, что означает, что каждый фрагмент данных, которыми управляет Redis, также хранится в оперативной памяти. Позволяет вызвать оперативную память, необходимую Redis для работы  оперативной памяти , и назвать оперативную память, используемую для хранения  данных, оперативной памятью пользователя .

какова скорость воздушного потока порожней ласточки?

Мы начнем наше путешествие с быстрого взгляда на оперативную память Redis.

Он используется для многих целей и задач, которые выполняет Redis, и один из способов представить себе этот кусок оперативной памяти — это вся память, используемая Redis для всего, что не является данными пользователя (я, вероятно, буду вникать в это по колено это позже) На объем оперативной памяти Redis влияет множество факторов развертывания, в том числе:

  • Архитектура процессора сервера
  • Операционная система
  • Версия и конфигурация Redis
  • Вероятно, много moar KKs, KUs и UUs

Однако мы можем легко установить базовый уровень для оперативных требований Redis к оперативной памяти, исследуя его в состоянии покоя на типичном сервере. Например, объем памяти  незаполненного экземпляра African swallow v3.0.0 на виртуализированном 64-разрядном сервере Ubuntu 14 составляет 7995392 байта (или около 7,6 МБ). Вы можете быстро определить, сколько общего ОЗУ вашего экземпляра Redis выделено из командной строки, с помощью ps-столбца RSS или команды Redis  INFO  :

foo@bar:~$ uname -a
Linux bar 3.13.0-49-generic #81-Ubuntu SMP Tue Mar 24 19:29:48 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
foo@bar:~$ ps aux | grep redis-server
foo 20139 0.0 0.1 42304 7808 pts/1 Sl+ 19:18 0:00 ./redis-server *:6379
foo 20143 0.0 0.0 15940 944 pts/9 S+ 19:18 0:00 grep --color=auto redis-server
foo@bar:~$ redis-cli INFO memory | grep used_memory_rss
used_memory_rss:7995392

Примечание: результаты двух вышеуказанных методов и других методов не всегда могут быть одинаковыми. Также обратите внимание, что used_memory_rss сильно отличается от used_memory в Redis, как мы увидим.

Поскольку это только что инициализированный экземпляр Redis, мы можем предположить, что эта цифра является верным представлением нашей операционной базы. Оперативная память Redis может вырасти, даже значительно, но пока не будем об этом беспокоиться.

что? ласточка с кокосом?

Redis красива , но вы не держите его только ради красивого лица, не так ли? Нет, вы заставляете Redis управлять своими данными, потому что вам нужна самая быстрая база данных NoSQL на планете сегодня. Вы позволяете ему нести свой кокос и зависите от него, чтобы он продолжал бить крыльями сорок три раза (так близко!) Каждую секунду. Так сколько оперативной памяти занимают данные пользователя? Это зависит от кокоса 🙂

Схема Redis без схемы * основана на модели Key-Value. Каждый пользовательский набор данных, которым управляет Redis, является в основном парой KV. Не нужно быть гением, чтобы понять, что чем длиннее / больше ваши ключи и значения, тем больше ОЗУ Redis потребуется для его хранения. Но в Redis есть несколько хитрых приемов, предназначенных для сжатия и систематизации данных.

* Нет такой базы данных без схемы — в большинстве случаев она может быть только неявной.

Давайте рассмотрим пример с простейшим типом данных Redis — рассмотрим следующее:

127.0.0.1:6379> SET swallow coconut
OK

Сколько оперативной памяти мы только что использовали? Поскольку все данные организованы по ключам, имя ключа — это первый элемент, который мы рассмотрим. Мы знаем, что имена ключей Redis — это двоичные безопасные строки, длина которых может достигать 512 МБ. Прохладно. Строковые значения в Redis также являются бинарно-безопасными и имеют размер до 0,5 ГБ, поэтому в нашем примере выше мы можем принять 7 байтов для «ласточки» и еще 7 байтов для «кокосового ореха» … и мы будем ошибаться, по крайней мере частично , Здесь, позвольте мне показать вам:

127.0.0.1:6379> STRLEN swallow
(integer) 7
127.0.0.1:6379> DEBUG SDSLEN swallow
key_sds_len:7, key_sds_avail:0, val_sds_len:7, val_sds_avail:0

Как показано выше для  STRLEN , Redis настаивает на том, что длина значения («кокосовое»), которое хранится под ключом «ласточка», составляет 7 байтов. Более того, «секретная» команда DEBUG SDSLEN также предъявляет те же требования, но то, что оба не учитывают, — это накладные расходы, и каждая структура данных Redis имеет свой собственный багаж. Это означает, что помимо реальных строк («ласточка» и «кокос»), Redis также требуется некоторая оперативная память для управления ими.

Поскольку каждый кортеж со значением ключа в Redis использует дополнительную оперативную память для своей внутренней бухгалтерии, и поскольку объем этой оперативной памяти зависит от структуры данных и самих данных, я считаю эти издержки, в то время как мета, частью пользовательских данных. Иными словами, если для каждой строки X байтов Redis требуется X + Y байтов, то Y — это определенно KU, который я хотел бы превратить в KK.

теория струн

Строки в Redis в основном реализованы одним из подпроектов Salvatore Sanfilippo @ antirez, который называется  sds  (или библиотека Simple Dynamic Strings для C). Несмотря на то, что строки sds обеспечивают большую мощность и простоту использования внутри Redis, они несут некоторые накладные расходы, так как строка sds состоит из:

+--------+-------------------------------+-----------+
| Header | Binary safe C alike string... | Null term |
+--------+-------------------------------+-----------+
|
`-> Pointer returned to the user.

(диаграмма предоставлена ​​Антирезом,  https://github.com/antirez/sds/blob/master/README.md )

Размер заголовка строки sds ( на данный момент ) составляет 8 байт, а нулевой символ — дополнительный байт, что дает нам в общей сложности 9 байтов на строку. «Ласточка» длиной 7 байт внезапно требует более чем вдвое больше — 16 байт оперативной памяти — для хранения в Redis!

Примечание: он на самом деле использует moar. Ссылка на каждый ключ также хранится в хэш-таблице пространства ключей Redis, которая, в свою очередь, требует еще больше оперативной памяти… И есть также «объект» robj, который Redis использует для упрощения некоторых вещей, таких как LRU… Но давайте просто сохраним накладные расходы на управление памятью ключа как КУ и выбросить его в оперативную часть дома на данный момент 🙂

… действительно четыре, если у них был кокос на линии между ними

Возвращаясь к нашим ласточкам и кокосам — теперь мы знаем, что Redis будет использовать 36 байтов для хранения двух строк, составляющих ключ и значение в приведенном выше примере, но это все? Давайте внимательнее посмотрим на наш кокос:

127.0.0.1:6379> OBJECT ENCODING swallow
"embstr"

Сюжет утолщается (или, может быть, это растут кокосовые волосы?). Этот загадочный ответ требует объяснения, но все ли кокосовые орехи закодированы одинаково? Давайте попробуем нести несколько разных форм кокосовых орехов и посмотрим:

127.0.0.1:6379> SET swallow:0 "0"
OK
127.0.0.1:6379> SET swallow:1 "An oversized and thickly-haired coconut"
OK
127.0.0.1:6379> SET swallow:2 "Ok, this is the mother of all coconuts - it is something that would make Donkey Kong run back to his mama in tears"
OK
127.0.0.1:6379> OBJECT ENCODING swallow:0
"int"
127.0.0.1:6379> OBJECT ENCODING swallow:1
"embstr"
127.0.0.1:6379> OBJECT ENCODING swallow:2
"raw"

Каждый из наших кокосов отличается, поэтому Redis использует разные кодировки. Кодировка «int» используется для эффективного хранения целочисленных значений между  LONG_MIN  и  LONG_MAX  (как определено в вашей среде  limit.h ), а также использует конструкцию shared.integers, чтобы избежать дублирования данных. Следовательно, они занимают меньше места. С другой стороны, строки длиной более 39 байтов хранятся как «сырые», тогда как более короткие строки используют кодировку «embstr» (магическое число определяется  REDIS_ENCODING_EMBSTR_SIZE_LIMIT  в  redis.h ).

собираюсь (кокос) орехи

А как насчет других структур кокосового ореха? Строки — это самая простая структура данных, которую предлагает Redis, и они используются внутри для создания других, более сложных структур. Хеш состоит из набора строк (полей и значений), добавленных со структурой данных словаря, в которой каждая запись представляет собой связанный список… НО они могут быть закодированы полностью как ziplist. И если говорить о списках, у нас есть связанные списки и ziplists (и , возможно , даже Мэтт Stancliff @ mattsta в  списки быстрого  скоро), которые также используются наборы и сортируют Наборы …

Я мог бы бесконечно углубляться в тонкие тонкости кодирования данных в Redis и их влияние на потребление памяти. Боюсь, однако, что это скоро нас всех утомит. Кроме того , вы можете  мерзавец фотографии  в  исходном коде  и начать читать его — я знаю несколько людей , которые сделали это, но вам нужен определенный уровень навыков программирования для этого.

Что еще оставляет большой KU —  Сколько оперативной памяти нужно Redis?  — и его младший брат KU — Сколько оперативной памяти нужно кокосам?  — почти без ответа. Но там, где есть воля, есть способ. Не стесняйтесь общаться со мной по обычным каналам — я очень доступен 🙂

Примечание: продолжение следует.