Pull to refresh

Сравнение MemCache и MongoDb для сетевого кэша

Reading time 7 min
Views 9.8K
Возникла достаточно неординарная идея: виде средства сетевого кеша взять не MemCache, а MongoDb и сравнить их производительность. Но для представления и сравнения показателей этих двух «механизмов кеширования» взяли еще и другие средства, позволяющие ускорить работу нашего App (APC, RamFS, TmpFS, XCache).
В статье приведены данные и графики сравнения этих механизмов с описанием и рассуждением полученных данных и графиков.

Любой большой интернет-ресурс рано или поздно сталкивается с проблемой нагрузок на сервер. Все бы ничего, если у Вас всего один сервер, ну или скажем связка Web-сервер + DB-сервер. В общем, все относительно неплохо, если у Вас всего один фронт-энд (Front-end). Но вот проблемы появляются при увеличении Вашего «зоопарка» серверов! Мало того, что у Вас усложняется иерархия связей Ваших серверов, так у Вас появляются еще такие проблемы как централизированное хранение данных — это касается БД, статических файлов и, конечно же, самих файлов кэша.

На работе мы разрабатываем достаточно крупный интернет-ресурс, который уже давно вышел за рамки одного сервера. Благо пока ограничиваемся web-сервером и DB-сервером. Однако начальство сейчас затеяло новый крупный проект, в котором уже на уровне проектировки и продумывания видна ее сумасшедшая структура. Перед небольшой группой программистов сейчас стоит новая и интересная задача: продумать структуру и иерархию проекта, с размерами которого еще ни один из нас лично не сталкивался ранее. Но речь сейчас не об этом проекте, а о выплывающих из его разработки проблем, а именно основной из них — централизированное хранение кэша.

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

Приступим к основной части статьи, а именно к нашему разбору полетов.
Для сравнения производительности кеширования были выбраны следующие средства кеширования: APC, MemCache, RamFS, TmpFS, XCache, а также (неординарный выбор) достаточно быстрая СУБД MongoDB.

Думаю, что нужно начать с того, как мы устанавливали все эти программы и расширения, и с какими трудностями мы столкнулись.
Все эксперименты производились на системе CentOS с 2Gb памяти и установленным PHP [5.3.6], а для большей справедливости, настройку ни одного пакета не проводили, все было взято «с коробки».

Установка APC [3.1.9]:
Тут все просто и легко. Через pecl устанавливаем пакет и все, APC работает.

Установка memcache [2.2.6]:
Тоже достаточно просто. Также через pecl устанавливаем пакет, а затем отдельно устанавливаем саму программу memcache, т.к. это не расширение, а сторонняя программа, которую необходимо устанавливать отдельно, но это не составляет труда. После установки все чудесно заработало.

Установка RamFS:
Это даже больше создание, чем установка. Делается все тоже очень просто: mount -t ramfs -o size=1024m ramfs /tmp/ramfs, тут мы выделяем 1Gb памяти и монтируем ее как файловую систему в директорию /tmp/ramfs.

Установка TmpFS:
Также, как и в прошлом случае, это создание, а не установка. Создается командой mount -t tmpfs -o size=1024m tmpfs /tmp/tmpfs, по которой видно что мы также выделяем 1Gb памяти и монтируем ее как файловую систему в директорию /tmp/tmpfs.

Заметка:
Основные различия между RamFS и TmpFS, которые нас интересуют, заключаются в следующем: оба метода работают почти одинаково, за исключением того, что при достижении выделенного лимита для RamFS, система не сообщит нам о достижении предела используемого объема и записываемые Вами новые данные будут просто пропадать в никуда, а TmpFS (также при достижении выделенного лимита) выдаст сообщение о нехватке места, при этом более старые данные будут перемещены в swap, то есть будет осуществлены дисковые операции, что собственно нас и не устраивает. Как RamFS так и TmpFS будут обнулены и пропадут при перезапуске системы, поэтому, если Вы хотите использовать их и после перезапуска системы, Вам необходимо поместить в автозагрузку скрипт создания данных разделов заново.


Установка XCache [1.3.1]:
А вот тут начинается уже интересное, с чем мы столкнулись. Установка данного пакета оказалась достаточно праблематичная из-за того, что в системе был установлен еще и PHP 5.2 (а он в системе на данный момент является основным), у XCache большой список зависимостей, вот установка данного пакета и являлась проблематичной из-за необходимости подсунуть ему нужные библиотеки. Но даже на этом проблемы с данным расширением не окончились, так как после установки (а стал он вроде как нормально) во время запуска скрипта с тестом для проверки корректности работы данного расширения возникли новые проблемы, заключающиеся в том, что при попытке записи переменной в память возникала ошибка:

Warning: xcache_set(): xcache.var_size is either 0 or too small to enable var data caching in /usr/local/php5.3/xcache.php on line 6

а следом за ней была следующая:

Warning: xcache_get(): xcache.var_size is either 0 or too small to enable var data caching in /usr/local/php5.3/xcache.php on line 10

Спустя 2 дня борьбы с данной ошибкой при помощи прямых рук, клавиатуры и бубна, результат был нулевой. Были догадки что неверно собрана *.so, однако замена нами собранной *.so на скачанную с интернета той же версии ни к чему не привела. В ход пошел дядя Гугль, была найдена точно такая же проблема StackOverflow. Однако решение данной проблемы так и не нашли, поэтому вынуждены были проводить дальнейшие тесты без XCache. Особого разочарования не было, потому что ранее проводимые тесты показали, что разница между APC и XCache почти незначительна, однако проблем с XCache гораздо больше.

Установка MongoDB [1.8.1]:
Установка Mongo достаточно простое и описывать его процесс не стану, однако запуск с необходимой нам конфигурацией приведу:
/usr/local/mongodb/bin/mongod --dbpath /usr/local/mongodb/data --profile=0 --maxConns=1500 --fork --logpath /dev/null --noauth --diaglog=1 --syncdelay=0
Основной параметр, который нас интересует, это последний "--syncdelay=0", который указывает время синхронизации данных, находящихся в памяти с данными на HDD. Указанное значение 0 говорит о том, что мы явно запрещаем Mongo синхронизацию с HDD, данная возможность описывается создателями СУБД, однако не рекомендуется по причине того, что при любом скачке электричества или другом сбое системы, которые могут затронуть демона Mongo, все Ваши данные будут утеряны. Нас данный риск устраивает вполне, т.к. хотим попробовать использовать данную СУБД в качестве кеширующего механизма.

Вроде все установлено и «настроено», теперь приступаем непосредственно к самим тестам.

Для большей честности будем проводить тесты с 4-мя сохраняемыми объемами данных: 4Kb, 72Kb, 144Kb, 2.12Mb.

Рассмотрим полученные данные на графиках:

4Kb:
image
Как видно на 1-ом графике (График времени записи 4Kb данных) — MemCache показал худший результат, после него идут RamFs и TmpFs, затем Mongo и APC.

image
На 2-м графике (График времени чтения 4Kb данных) отчетливо видно как Mongo пасет задних, в то время как MemCache почти сравним с RamFs и TmpFs, которые почти совпали, просто на данном графике расхождения между ними почти незаметны.

72Kb:
image
С 3-го графика (График времени записи 72Kb данных) видно как неадекватно себя повел MemCache, а Mongo вполне предсказуемо. Очень удивительно, что APC, RamFs и TmpFs почти совпали.

image
А вот чтение, отображенное на 4-м графике (График времени чтения 72Kb данных): Mongo сдал позицию и пропустил своего конкурента MemCache вперед, как и ранее APC — лидер всей гонки.

144Kb:
image
Начиная с 5-го графика (График времени записи 144Kb данных) мы видим уже странное поведение почти всех систем — MemCache очень нестабильно себя ведет и иногда на меньшем кол-ве итераций время даже выше чем на большем, а еще удивительней то, что ближе к 500 итерациям Mongo начинает обгонять APC! RamFs и TmpFs держат удивительно высокую планку в скорости.

image
На 6-м графике (График времени чтения 144Kb данных) Mongo всем проигрывает, а APC самый шустрый.

2.12Mb:
image
На 7-м графике (График времени записи 2.12Mb данных), Mongo оказался очень стабильным, однако последняя итерация в 500 раз выбила его из колеи, но он удержался в седле. Конечно обсалютный лидер это APC, а вот с MemCache, TmpFs и RamFs происходит нечто интересное, что будет описанно ниже.

image
На последнем графике (График времени чтения 2.12Mb данных) также очень чудная картина: TmpFs вышел самый медленный, а RamFs самый быстрый. Еще один удивительный момент, что Mongo обошел APC!

Если посмотреть на последние итерации последних 2-х графиков, в которых кешировались файлы по 2.12Mb 500 раз, можно заметить достаточно интересную вещь, что 500 (кол-во итераций) * 2.12 (размер одного файла) = 1`060Mb, что говорит нам о том, что в RamFS и TmpFS мы вышли за предел максимального объема! Поэтому и цифры достаточно интересные и непредсказуемые.
На самом деле все вышло как раз предсказуемо: при достижении верхнего лимита (а у нас это 1024Mb) RamFS просто перестает записывать данные и игнорирует команды на запись. При чтении этих данных физически чтение не происходит, а просто возвращает пустую строку (при обработке на PHP строка не пустая, а интерпретируется как null), а TmpFS в это время ведет себя как раз наоборот — он все наши данные записывает, предварительно выделяя для них место, передвигая более старые данные в swap. Этим и объясняется то, что при таких объемах и подобных кол-вах итераций RamFS занимает достаточно малое время на обработку записи и еще менее — на чтение несуществующих данных, а TmpFS наоборот сильно увеличивает это время из-за необходимости совершать дисковые операции.
Как я указывал выше, все средства были взяты «с коробки», настройка данных средств не осуществлялась, поэтому время у memcache равно 0, т.к. записываемый объем одной записи размером в 2.12Mb просто превышает максимальный объем одной хранимой записи в memcache. Для того, чтобы в memcache можно было хранить данные, размер которых более 2.12Mb, необходимо пересобрать сам memcache, но тогда нужно было бы соответственно настраивать и все остальное, но одинаково настроить разные продукты почти не реально, поэтому я позволил себе оставить данный нюанс в таком виде, в каком он сейчас. Возможно это и не верно, однако нас больше интересовало именно поведение всех этих средств в равных условиях — «с коробки».

Глядя на все эти данные каждый разработчик может сделать свой вывод и свои заключения чем и как пользоваться. Мы же сделали свои выводы, которыми и поделимся:
По причине того, что нас интересуют данные тех средств, которые позволяют кешировать по сети, обсудим MemCache и Mongo. Конечно, во многих случаях, как это видно на графиках, MemCache обходит Mongo при чтении, что более релевантней чем запись, в которой Mongo обходит MemCache. Однако если учесть все те возможности, которые нам дает MongoDb, что конечно понятно, ведь это полноценная СУБД со всеми своими возможностями и простотой работой с ней, то те недостатки в скорости, которые показывает Mongo, с легкостью можно перекрыть ее способностью делать сложные выборки и получение нескольких записей (записей кэша) одним запросом. Еще один плюс MongoDb перед MemCache: при правильной и продуманной архитектуре App можно получать закешированные элементы страницы одним запросом, а уже после получения ответа от Mongo анализировать пришедшую информацию и выполнять необходимые действия и кеширование надостающих блоков.

Также можно и продумать систему таким образом, чтобы был многоуровневый кэш: кэш первого уровня (сетевой кэш) MemCache или Mongo, а кэш второго уровня APC или XCache (но тут еще требуются сравнение).

В ближайшем будущем намечается более углубленный анализ и сравнение MemCache и Mongo — сравнение не только затраченного времени, но и затраченного объема памяти с замером нагрузки на процессор и на сервер в целом.

Напоследок хочется указать то, что тесты запускались неоднократно и данные, приведенные в таблицах — это среднее значение из 10-20 повторений тестов.
Приводить табличные данные тестов не стану из-за большого объема.
Tags:
Hubs:
+29
Comments 46
Comments Comments 46

Articles