...

понедельник, 16 января 2017 г.

Redmine на MySQL с RocksDB быстрее, чем с InnoDB, от 20% до 3 раз

Мы собрали форк MySQL от Facebook с движком RocksDB вместо InnoDB и потестировали его с реальными приложениями: Drupal, Wordpress, Redmine.


Это офигенная штука. При низкой нагрузке выигрыш маленький, десятки процентов. Зато при высокой нагрузке выигрыш в разы. Когда RocksDB добавят в стабильный релиз в MariaDB, я уверен, что в течение полугода половина народа перейдет с InnoDB на RocksDB. Особенно, небольшие сайты на cloud/VPS и выделенных серверах.


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


Я собрал в статью результаты тестирования реальных сценариев Redmine, добавил анализ результатов и выводы. Redmine на MySQL с RocksDB оказался быстрее, чем с InnoDB — от 20% при минимальной нагрузке до 3 раз при максимальной. Позже подготовлю материалы по Drupal и другим PHP-приложениям.


Вы сможете проверить работу MyRocks и самостоятельно — в конце статьи есть ссылки на инсталляторы и виртуальные машины с LAMP/LEMP/Ruby стеками, собранные с MyRocks вместо MySQL.




Введение


Facebook на базе своего хранилища RocksDB создал storage engine для MySQL — MyRocks. Работающая реализация MyRocks в виде MySQL 5.6 с патчами от Facebook передана в open source и размещается на GitHub — http://ift.tt/1amdJDp. MyRocks является альтернативой InnoDB и дает несколько преимуществ:


  • Снижение объема записи
  • Лучшая компрессия
  • Уменьшения случайных чтений

Все это в сумме существенно повышает скорость транзакций на HDD и уменьшают изнашиваемость SSD, а также ускоряют репликацию.


MariaDB и Percona уже ведут работы по интеграции MyRocks в свои форки MySQL: Facebook MyRocks at MariaDB, Announcing MyRocks in Percona Server for MySQL. MariaDB объявила, что MyRocks будет доступен в release candidate 10.2 этой зимой. На Jetware в число альтернатив MySQL добавлена оригинальная реализация MyRocks от Facebook на базе MySQL 5.6.


Тестирование производительности на синтетических тестах показывает впечатляющие результаты. В зависимости от типа устройства хранения, выигрыш по скорости составляет от 20% до 10x. Результаты тестирования LinkBench можно посмотреть в публикации Yoshinori Matsunobu MyRocks: A space- and write-optimized MySQL database и в блоге Mark Callaghan, например, MyRocks: use less IO on writes to have more IO for reads. Эти тесты во многом ориентируются на большие объемы баз данных (десятки и сотни гигабайт) и мощные машины.


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


Первым мы тестируем Redmine. Мы знаем как он устроен, активно используем его в разработке и поэтому тестирование имеет для нас также практическую ценность — если результат окажется хорошим, мы переходим на MyRocks.


Условия тестирования


Программное обеспечения


Мы используем Redmine 3.3.1 с Ruby 2.3.1, в конфигурации по умолчанию, без дополнительных плагинов.


В качестве серверов баз данных используем:



Все бинарники собраны одним компилятором GCC 4.9.3, с рекомендуемыми параметрами сборки и оптимизации.


Операционная система — Ubuntu 14.04 x86_64, Linux kernel 3.13.0. Файловая система — ext4.


Наборы данных


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


  1. Малый набор
    • 30 пользователей
    • 3 проекта и 10 подпроектов второго уровня, в каждом проекте по 10 пользователей
    • 1000 задач с 10 комментариями каждая
  2. Большой набор
    • 1000 пользователей
    • 10 проектов первого, 100 подпроектов второго и 10 подпроектов третьего уровня, в каждом проекте по 10 пользователей
    • 10000 задач с 10 комментариями каждая
  3. Гигантский набор
    • 10000 пользователей
    • 100 проектов первого, 1000 подпроектов второго и 100 подпроектов третьего уровня, в каждом проекте по 10 пользователей
    • 100000 задач с 10 комментариями каждая

Большинство реальных случаев использования Redmine приходятся на размеры между Малым и Большим. Объемы уровня Гигантского бывают значительно реже.


Объем занятого пространства



Исходные данные


Столбцы показывают объемы занятого пространства для разных баз данных и разных наборов данных (меньше — лучше)


Оборудование


  • Процессор: 4-core Xeon E31220 3.10GHz
  • Память: 16 Gb RAM, DDR3 1333
  • HDD: RAID mirror, 2 x Western Digital RE4 1 Tb

Виртуальная машина


Мы имитируем работу Redmine в условиях, близких работе у облачного провайдера или на офисном сервере. Для этого мы выделяем не весь физический сервер, а размещаем его в виртуальной машине с гораздо меньшим количеством ресурсов и имитируем различную нагрузку на дисковую систему со стороны соседей. В качестве платформы виртуализации используется Xen 4.6, в dom0 — Linux kernel 3.16.7. Устройство хранения разбивается с помощью LVM, обычное linear, без thin provision и снэпшотов. Том размещается посередине HDD.


Использовались три конфигурации виртуальных машин:


  1. 1 Gb RAM, 4 CPU, HDD 16 Gb
  2. 2 Gb RAM, 4 CPU, HDD 16 Gb
  3. 8 Gb RAM, 4 CPU, HDD 16 Gb

Тестируемые операции


Мы проверяем скорость работы наиболее часто используемых в Redmine операций — создание задач, добавление комментариев к задачам, изменение статуса и ответственного лица задачи. Из этих операций мы создали два теста, два рабочих цикла задачи:


  • Создание задачи


    Создание задачи в проекте одним участником проекта, назначение ее на другого участника проекта и добавление в нее 10 комментариев от лица других участников проекта.


  • Обработка 10 задач


    Получение пользователем 10 назначенных на него задач, переведение их всех в In Progress, и затем поочередное переведение задачи в Resolved и назначение ее на создателя задачи.



Тесты проводятся на 1, 2 и 4 параллельных процессах Redmine.


Сторонняя нагрузка на диск


Нагрузка создается с помощью утилиты fio, которая читает и пишет 50/50 случайные блоки в оставшуюся часть диска. Мы имитировали несколько уровней нагрузки на диск, которые характерны для типовых случаев работы виртуальных машин — у провайдеров публичных облаков и VPS, или при запуске на собственном сервере нескольких виртуальных машин под VMWare, Hyper-V, KVM или XenServer.


Для имитации неполной загрузки мы запускаем fio с ограничением IOPS с помощью ключа --rate_iops и замеряем утилизацию диска. При 100% однопоточной нагрузке это около 80 IOPS. Утилизация 25% создается нагрузкой 14 IOPS. Большая нагрузка имитируется увеличением числа потоков ключем --iodepth.


В зависимости от количества соседних виртуальных машин, характера их работы и пиков нагрузки, загруженность диска может серьезно отличаться как у облачных провайдеров и VPS, так и на собственном сервере. Поэтому мы проводили тестирование при отсутствии сторонней нагрузки, при незначительной однопоточной нагрузке (14 IOPS, 25%), так и при и полных сторонних нагрузках в 1, 2 и 4 потока.


Измеряемые значения


Мы измеряем полное время выполнения каждой операции Redmine на большом числе операций и сравниваем среднее время выполнения. Первые 10% результатов игнорируются — на них мы разогреваем систему. Последние 10% результатов игнорируются для того, чтобы исключить хвостовое искажение из-за разного времени завершения параллельных процессов.


Измерения проводятся в разных комбинациях условий:


  • для разных конфигураций виртуальных машин и разных наборов данных
  • для разного числа параллельных процессов Redmine (основная нагрузка) и разных сторонних нагрузок на диск

Время выполнения замеряется для всех трех баз — MyRocks MySQL, MySQL и MariaDB. Мы также вычисляем разницу в скорости MyRocks MySQL по отношению к MySQL и MariaDB. Собранные данные представлены в виде графиков.


Результаты тестирования


Малый набор данных и малая виртуальная машина


  • Виртуальная машина: 1 Gb RAM, 4 CPU, HDD 16 Gb
  • Набор данных: 30 пользователей, 13 проектов и подпроектов, 1000 задач

Графики времени выполнения операций


1) создание задачи; 2) обработка 10 задач



Исходные данные


Столбцы показывают время выполнения операции (меньше — лучше). Линии показывают во сколько раз сервер MySQL или MariaDB был медленнее сервера MyRocks MySQL.


Минимальная нагрузка — один процесс Redmine и отсутствует сторонняя нагрузка. Максимальная нагрузка — 4 процесса Redmine и 4 полных потока сторонней нагрузки на диск.


Мы видим, что время создания задачи для MyRocks при увеличении нагрузки до максимума меняется незначительно, и возрастает от 0.018 сек до 0.023 сек, на 23%. Для MySQL и MariaDB минимальное время создания задачи составляет 0.022 сек и возрастает в десять раз до 0.23 сек при максимальной нагрузке. При минимальной нагрузке MySQL и MariaDB оказываются медленнее на 24%, чем MyRocks; при максимальной нагрузке они оказываются медленнее в 9.5 раз.


Время обработки задач для MyRocks вырастает от 0.245 сек при минимальной нагрузке до 0.327 сек при максимальной, на 33%. Для MySQL и MariaDB минимальное время обработки задач возрастает примерно в 7 раз — с 0.283 сек при минимальной нагрузке до 2.245 сек при максимальной.


Объема оперативной памяти не хватает для эффективного кэширования чтения, и это очень сказывается на скорости InnoDB.


Большой набор данных и средняя виртуальная машина


  • Виртуальная машина: 2 Gb RAM, 4 CPU, HDD 16 Gb
  • Набор данных: 1000 пользователей, 120 проектов и подпроектов, 10000 задач

Графики времени выполнения операций


1) создание задачи; 2) обработка 10 задач



Исходные данные


Столбцы показывают время выполнения операции (меньше — лучше). Линии показывают во сколько раз сервер MySQL или MariaDB был медленнее сервера MyRocks MySQL.


Минимальная нагрузка — один процесс Redmine и отсутствует сторонняя нагрузка. Максимальная нагрузка — 4 процесса Redmine и 4 полных потока сторонней нагрузки на диск.


В данной конфигурации ресурсы виртуальной машины лучше соответствуют объему данных и нагрузке. Для MyRocks время создания задачи остается прежним — от 0.018 сек до 0.023 сек, вырастая на 23%. Для MySQL и MariaDB минимальное время становится чуть больше — 0.023 сек и вырастает только в два раза — до 0.056 сек при максимальной нагрузке. Они оказываются медленнее, чем MyRocks, на 30% при минимальной нагрузке, и в 2.3 раза при максимальной.


Для обработки задач ситуация похожая. Время выполнения у MyRocks при увеличении нагрузки слабо растет от 0.248 сек до 0.331 сек. Для MySQL и MariaDB минимальное время уже на 10% больше, чем для Малого набора данных и составляет 0.296 сек. При максимуме нагрузки время увеличивается почти в два раза — до 0.595 сек. MySQL и MariaDB оказываются медленнее, чем MyRocks, на 18% при минимальной нагрузке и на 80% при максимальной.


Гигантский набор данных и большая виртуальная машина


  • Виртуальная машина: 8 Gb RAM, 4 CPU, HDD 16 Gb
  • Набор данных: 10000 пользователей, 1200 проектов и подпроектов, 100000 задач

Графики времени выполнения операций


1) создание задачи; 2) обработка 10 задач



Исходные данные


Столбцы показывают время выполнения операции (меньше — лучше). Линии показывают во сколько раз сервер MySQL или MariaDB был медленнее сервера MyRocks MySQL.


Минимальная нагрузка — один процесс Redmine и отсутствует сторонняя нагрузка. Максимальная нагрузка — 4 процесса Redmine и 4 полных потока сторонней нагрузки на диск.


Десятикратное увеличение объема данных немного увеличило время создания задачи для всех баз: 0.020 сек для MyRocks, 0.026-0.029 для MySQL и MariaDB. Увеличение нагрузки замедляет MyRocks на 35% до 0.027 сек. Для MySQL и MariaDB рост нагрузки сказывается на скорости больше — при максимальной нагрузке время увеличивается в 3 раза — до 0.088 сек, и они оказываются медленнее, чем MyRocks, в 3.2 раза.


При обработке задач время выполнения MyRocks увеличивается на 32%, от 0.255 до 0.33 сек. У MySQL и MariaDB время увеличивается в 4 раза — с 0.309 до 1.242 сек. И они отстают от MyRocks в 3.8 раз.


Объем данных уже вырос до таких размеров, что начинают сказываться задержки случайной записи при обновлении индексов InnoDB и разница в скорости между RocksDB и InnoDB при максимальных нагрузках снова выросла.


Анализ результатов


Объем памяти


Для работы Redmine объем 1 Gb является минимальным рекомендуемым. Для эффективного кэширования данных в page cache размер памяти уже недостаточен, поэтому скорость работы очень чуствительна к нагрузке на диск. Задержки возникают уже на SELECT-запросах, так как для них приходится считывать данные с диска. Меньший объем хранимых данных у RocksDB привел к более эффективному кэшированию чтения, чем для InnoDB. Поэтому даже при большой нагрузке скорость операций у MyRocks изменилась совсем незначительно.


При увеличении памяти до 2 Gb основные используемые данные уже вмещаются в page cache и серверу БД уже не нужно постоянно их считывать с диска. В этом случае диск является узким горлышком только при изменениях в базе. Транзакции записываются на диск без writeback cache и интенсивная дисковая нагрузка увеличивает время ожидания завершения записи.


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


Скорость RocksDB vs InnoDB


Исходя из принципа работы RocksDB, мы ожидали ускорения при выполнении транзакций. На синтетических тестах производительности разработчики получали 10-кратный прирост скорости в работе СУБД. Для приложений, таких как Redmine, время выполнения операции состоит из времени выполнения Ruby-скрипта и времени выполнения запроса в БД. Разумеется, замена storage engine на RocksDB никак не увеличит скорость работы Ruby, и эта составляющая остается неизменной. Но и с учетом этого прирост в скорости за счет ускорения БД оказался впечатляющим.


Здесь мы приводим краевые результаты тестирования для виртуальной машины 2 Gb и Большого набора данных, и для виртуальной машины 8 Gb и Гигантского набора данных. Мы не учитываем здесь тестирование на высокой нагрузке для виртуальной машины 1 Gb, так как это случай экстремальной нехватки ресурсов.


Графики времени выполнения операций


1) создание задачи; 2) обработка 10 задач



Столбцы показывают время выполнения операции (меньше — лучше)


Минимальная (1 процесс Redmine без сторонней дисковой нагрузки) и максимальная нагрузка (4 процесса Redmine и 4 потока полной сторонней нагрузки на диск)


При низкой нагрузке Redmine на MyRocks оказался на 15%-25%, быстрее, чем на MySQL и MariaDB. Размер хранимых данных мало влияет на эту скорость и у RocksDB, и у InnoDB — увеличение числа задач Redmine в 10 раз увеличило время выполнения примерно на 10%.


При высокой нагрузке (увеличении числа параллельных процессов и повышении сторонней дисковой нагрузки) поведение полностью меняется. Отрыв MyRocks стал больше — от 2-кратного до почти 4-кратного. Размер хранимых данных также стал существенно влиять на скорость — 10-кратное увеличение числа задач Redmine заметно (в 1.5-2 раза) замедлило скорость выполнения на серверах с InnoDB, и менее заметно замедлило выполнение на RocksDB (0-15%).


Одновременное увеличение объема данных и высокая нагрузка замедлили работу Redmine с MyRocks в 1.5 раза, в то время как Redmine на MySQL и MariaDB стал медленнее в 4 раза.


Стабильность работы


При тестировании мы обнаружили нюанс поведения одного из SQL-запросов Redmine при поиске с учетом parent issues. Из-за него некоторые виды поиска оказывались медленнее в MyRocks. Но это небольшое упущение со стороны Redmine — parent_id не имел в таблице индекс. Также мы столкнулись с небольшим багом, приводящим к расходу CPU после некоторых конфликтных транзакций в MyRocks.


Мы не сталкивались с другими проблемами. По словам разработчиков, Facebook использует MyRocks в production уже давно.


Вы можете использовать MyRocks уже сейчас или дождаться более широкого тестирования после появления MyRocks в MariaDB release candidate 10.2 или в Percona Server for MySQL. Пакет MyRocks доступен в репозитории Jetware как одна из альтернатив mysqld в конструкторах стеков, например, PHP LAMP/LEMP), Ruby RAMP/REMP, или приложений, например, Redmine.


Несколько недель назад мы перевели свой внутренний Redmine-сервер на MyRocks и успешно в нем работаем.


Заключение


  1. Redmine с RocksDB оказался быстрее, чем с InnoDB — от 20% при минимальной нагрузке до 3 раз при максимальной.
  2. Увеличение объема данных и нагрузки, замедлившее Redmine с InnoDB в 4 раза, всего лишь в 1.5 раза замедлило Redmine с RocksDB.

P.S. Тестирование MyRocks с другими приложениями


В данном тесте мы проверили производительность MyRocks для приложения Redmine. В следующих тестах мы собираемся проверить производительность MyRocks с PHP-приложениями. Скорее всего, первым будет Drupal.


Статья на английском языке

Комментарии (0)

    Let's block ads! (Why?)

    Комментариев нет:

    Отправить комментарий