Виртуальная память в Redis

Виртуальная память (в статье для ее обозначения также будет употребляться аббревиатура VM) впервые появилась в версии Redis 2.0, предоставив возможность хранить значения редко используемых ключей не в памяти, а на диске. Redis использует модель "ключи-значения": существуют ключи, ассоциированные с некоторыми значениями. Обычно Redis хранит как ключи, так и ассоциированные значения в памяти. Иногда это не лучшее решение. Поэтому ключи должны храниться в памяти по умолчанию (чтобы обеспечить быстрый поиск), в то время как значения могут выгружаться на диск, если они редко используются. Эта возможность и называется виртуальной памятью. Когда редко используемые значения снова понадобятся клиенту, по соответствующему запросу они будут загружены из своп-файла в основную память. Объекты, попадающие в своп, в большинстве своем имеют наибольший "возраст" (то есть, количество секунд со времени последнего использования). Однако вероятность свопинга объекта также пропорциональна логарифму его размера в памяти.

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

1) Неравномерность доступа к данным. На малый процент ключей (например, относящихся к активным пользователям на вашем сайте) приходится подавляющее большинство обращений. В то же время, слишком много данных приходится на один ключ, чтобы хранить все это в памяти.

2) Просто не хватает ресурсов, чтобы держать все данные в памяти, независимо от шаблона поиска (например, босс урезал расходы на покупку и содержание серверов). Бывает, что и хранимые значения достаточно большие. В данной конфигурации Redis может использоваться в качестве дисковой БД с хранением ключей в памяти для быстрого поиска, но с более медленным дерганьем диска при доступе к реальным значениям.

Важно запомнить, что Redis не может свопить ключи. Поэтому если у вас проблемы из-за того, что вы держите слишком много ключей с маленькими значениями, то VM - это не решение. Между тем, если много памяти используется из-за очень больших значений (например, длинных строк, списков, наборов и хешей с большим количеством элементов), тогда включение VM становится хорошей идеей. Проблему "множества ключей с малыми значениями" можно превратить в проблему "немногих ключей с очень большими значениями", просто используя хеш-таблицы для группировки родственных данных в полях одиночного ключа.

VM включается и настраивается в конфигурационном файле redis.conf, на первом шаге нужно включить ее с помощью директивы:

vm-enabled yes
Настройка vm-max-memory определяет максимальный размер памяти, используемой Redis, перед началом свопинга значений на диск. Пока этот предел памяти не будет достигнут, не будет свопиться ни один объект, и Redis будет работать со всеми объектами в памяти, как обычно. При достижении лимита часть объектов будет выгружаться в память, чтобы размер используемой памяти был всегда чуть меньше лимита. Если ключи сами по себе будут занимать в памяти больше места, чем лимит, то настройка vm-max-memory работать не будет. Наилучшее значение для настройки vm-max-memory - это столько оперативной памяти, сколько хватит, чтобы спокойно работать с существующим набором данных. Просто выделите БД столько памяти, сколько можете, и свопинг в Redis будет работать максимально хорошо.

Своп-файл, использующийся в Redis для передачи данных из памяти на диск, не отвечает за работоспособность этих данных. Поэтому его можно удалить при прекращении работы объекта Redis. Однако его нельзя перемещать, удалять или изменять каким-либо другим способом во время работы Redis. Так как в большинстве своем доступ к своп-файлу случаен, запись его на твердотельный SSD-накопитель приведет к лучшей производительности. Своп-файл, как обычно, разделен на страницы. Значение может быть сохранено на одной или нескольких страницах, но на одной и той же странице не может быть больше одного значения. Нельзя напрямую сказать Redis, сколько байтов своп-файла ему нужно использовать. Вместо этого настраиваются два различных значения, затем перемножаются между собой, и так получается общее количество использованных байтов. Эти два значения - это количество страниц внутри своп-файла и размер страницы. Можно настроить эти два параметра в конфигурационном файле redis.conf:

1) Директива vm-pages определяет общее количество страниц в своп-файле.

2) Директива vm-page-size определяет размер страницы в байтах.

Следует осторожно настраивать эти директивы, например, сделать размер страницы таким, чтобы большая часть значений могла сохраняться на нескольких страницах своп-файла. В противном случае часть значений, не уместившихся в памяти, может не уместиться и в своп-файле.

За максимальное количество потоков для ввода-вывода при работе со своп-файлом отвечает директива vm-max-threads:

vm-max-threads 4
Рекомендуется выставлять эту директиву равной количеству ядер в вашей системе. Специальное значение директивы, равное "0", сделает виртуальную память блокирующей. При такой конфигурации VM будет проводить операции ввода-вывода в синхронном режиме блокировки. При блокирующей VM будет происходить следующее:

1) Клиенты, получающие доступ к ключам вне свапа, будут блокировать при чтении с диска других клиентов, работающих с данными в памяти, поэтому задержка для других клиентов будет больше, особенно если диск медленный или загруженный и/или в свопе на диске хранятся большие значения.

2) Производительность блокирующей VM в целом выше, так как не тратится время на синхронизацию, распараллеливание и возобновление блокированных клиентов, ожидающих получения доступа к значениям. Поэтому если вы готовы к более продолжительным задержкам, блокирующая VM может быть хорошим выбором. Особенно если свопинг происходит редко и большинство данных, к которым вы часто обращаетесь, помещается в памяти.

Если, напротив, у вас много операций записи и выгрузки из свопа; много ядер, которые хочется использовать; просто вы не хотите, чтобы клиенты, работающие со значениями из свопа блокировали других клиентов на несколько миллисекунд (или больше, если значение в свопе очень большое) - то лучше использовать многопоточную VM.

Своп-файл может быть достаточно большим: до 40 ГБ и больше. Не все файловые системы могут работать с такими большими файлами, например, Mac OS X часто работает с ними неправильно. Поэтому нужно использовать файловую систему с поддержкой разреженных файлов. В разреженных файлах много пустого содержимого. Расширенные файловые системы (NTFS, ext2, ext3, XFS, JFS, ReiserFS, Reiser4, UFS, Rock Ridge, UDF) могут кодировать такие файлы более эффективно. Это позволяет в обычном состоянии сжимать разреженные файлы, а когда необходимо, то есть, когда используются непустые блоки файла, выделять больше места для таких файлов. Своп-файл, конечно, относится к разреженным файлам, особенно если сервер работает недолго, или файл намного больше размера данных вне свапа. Файловая система без поддержки разреженных файлов сразу заблокирует процесс Redis во время создания очень большого файла.

Как после включения виртуальной памяти и запуска Redis узнать, сколько объектов в свопе, сколько объектов попадает в своп каждую секунду и т.д.? Для этого нужно воспользоваться утилитой redis-stat:

$ ./redis-stat vmstat
При включении VM сохранение и загрузка БД происходят гораздо медленнее. База данных, которая обычно загружается за 2 секунды, при включенной VM загружается 13 секунд, если сервер настроен на использование минимально возможного количества памяти (то есть, директива vm-max-memory выставлена 0). Поэтому, вероятно, вы захотите перейти на конфигурацию файла только для добавления и выполнять время от времени команду BGREWRITEAOF. Важно отметить, что пока выполняются команды BGSAVE или BGREWRITEAOF, Redis не свопит новые значения на диск. VM будет работать только в режиме чтения, когда кто-нибудь будет получать к ней доступ. Поэтому если у вас много операций записи во время работы другого клиента, использование памяти может расти.

Выставление директивы vm-max-memory в 0 позволяет превратить Redis в дисковую БД, хранящую в памяти только ключи. Если задержки доступа и меньшая производительность не критичны, и нужно использовать наименьшее количество памяти для очень больших значений, то такая настройка будет лучшим вариантом. В таком случае, вам следует сначала попытаться сделать виртуальную память блокирующей (vm-max-threads выставить в 0), так как при такой конфигурации и большом трафике количество операций записи и выгрузки из свопа будет огромным, и многопоточность будет съедать много ресурсов в сравнении с простой блокирующей реализацией.

Оцени публикацию:
  • 0,0
Оценили человек: 0

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2018 YaPro.Ru

Главная » Веб-мастеру » PHP »