Параллельная репликация — долгожданная функция MySQL. Он доступен в MariaDB 10.0 и MySQL 5.7. В этом третьем посте серии мы представляем результаты тестов в производственных средах Booking.com.

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

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

Чтобы получить ответы, нет ничего лучше, чем экспериментировать с технологией. Результаты тестов уже опубликованы (MariaDB 10.0: улучшение в 10 раз и MySQL 5.7: улучшение в 3–6 раз), но в наших производственных средах результаты могут отличаться. Лучшим тестом было бы запустить параллельную репликацию на наших реальных рабочих нагрузках, но это не тривиально. Для возможности параллельного выполнения транзакций ведомому устройству требуется информация о параллелизме от ведущего устройства (подробнее см. Часть 1). С мастером более старой версии (в нашем случае MySQL 5.6) у подчиненных нет этой информации.

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

Наши эталонные тесты устанавливаются в четырех производственных средах: E1, E2, E3 и E4. Каждая из этих сред состоит из одного рабочего мастера, нескольких промежуточных мастеров и подчиненного листа. Полное описание этих сред можно найти в приложении.

Подчиненная групповая фиксация определяет меньше параллелизма, чем параллельное выполнение на ведущем (подробности в разделе Групповая фиксация: ведомое против ведущего приложения). Даже в этом случае получаются приличные размеры групп, как показано на графиках размеров групповых коммитов в приложении. Обычно у нас есть группы размером не менее 5, в большинстве случаев они больше 10, а иногда они достигают 15 или даже 20. Это позволит нам протестировать параллельную репликацию с реальной рабочей нагрузкой.

Прежде чем закрыть это длинное введение, давайте немного поговорим о наших ожиданиях. InnoDB лучше использует много ядер (результаты тестов RO и RW), но однопоточная репликация мешает увеличить количество операций записи в среде репликации. Без параллельной репликации одно ядро ​​может использоваться на ведущем устройстве для выполнения операций записи без возникновения задержек ведомого устройства. Это разочаровывает, так как серверы имеют 12 и более ядер (для записи можно использовать только одно). В идеале мы хотели бы использовать значительный процент ядер сервера для записи (25% было бы хорошим началом). Таким образом, ускорение на 3 было бы хорошим результатом на данный момент (12 ядер), а в ближайшем будущем потребуется ускорение на 6 и 10 (24 и 40 ядер).

Тест: наверстать упущенное за 24 часа транзакций

Наш тестовый сценарий выглядит следующим образом: после восстановления резервной копии базы данных, запуска MariaDB, ожидания загрузки пула буферов и запуска подчиненного устройства в течение не менее 12 часов, мы измеряем время, которое потребовалось для обработки 24 часов. производственных операций.

Тесты выполняются в следующих конфигурациях двоичного журнала:

  • Главный посредник (IM): включены как двоичные журналы, так и log-slave-updates.
  • Подчиненный с двоичными журналами (SB): двоичные журналы включены, но log-slave-updates отключены.
  • Стандартное подчиненное устройство (SS): отключены как двоичные журналы, так и log-slave-updates.

И в следующих конфигурациях стойкости:

  • Высокая долговечность (HD): sync_binlog = 1 и innodb_flush_log_at_trx_commit = 1.
  • Нет долговечности (ND): sync_binlog = 0 и innodb_flush_log_at_trx_commit = 2 (также описывается/известно как расслабленная долговечность).

Для каждой из этих конфигураций (всего 6: IM-HD, IM-ND, SB-HD, SB-ND, SS-HD и SS-ND), тесты запускаются с разными значениями slave_parallel_threads (SPT). Полные результаты представлены в приложении, а наиболее интересные результаты представлены ниже (SB-HD и SB-ND). Представленное время представлено в формате часы:минуты.секунды. Ниже времени, необходимого для обработки 24-часовых транзакций, ускорение, достигнутое при однопоточном запуске, представлено жирным шрифтом.

В разделе График во время тестов приложения вы можете найти много подробностей о различных тестовых прогонах.

Обсуждение

Можно много чего сказать об этих результатах. Начнем с наблюдений, не связанных с параллельной репликацией (SPT=0):

  • Obs1: Результаты стандартного ведомого устройства (без бинарных логов) очень близки к результатам ведомого устройства с двоичными логами (без log-slave-updates) (подробности в приложении).
  • Obs2: log-slave-updates имеет видимую стоимость для E1 (разница во времени между IM-HD и SB-HD), менее очевидную, но все же заметную стоимость для Е2 и Е3, причем выигрывает Е4 (последнее настораживает, цифры в приложении).
  • Наблюдение 3: снижение долговечности — это огромный выигрыш для E1 и E2, более ограниченный выигрыш для E3 и гораздо меньший выигрыш для E4.

Ссылаясь на Obs1 выше, это показывает, что двоичные журналы, вероятно, не следует отключать на ведомом устройстве: затраты практически отсутствуют, а выигрыши велики (отслеживание ошибочных транзакций и кандидат на повышение уровня мастера). Однако подчиненные устройства с log-slave-updates работают медленнее, чем подчиненные устройства с включенным только двоичным журналом (Obs2 выше), поэтому по возможности следует избегать использования log-slave-updates. Binlog-серверы можно использовать для замены log-slave-updates для промежуточных мастеров, см. Масштабирование подчиненных серверов MySQL для получения дополнительной информации (см. также Лучшая параллельная репликация для MySQL для объяснения, почему log-slave-updates плохо работает на промежуточных мастерах для параллельной репликации).

Применительно к Obs3 выше это можно объяснить разной нагрузкой четырех сред (подробнее о нагрузках можно прочитать в приложении):

  • E2 — это рабочая нагрузка, связанная с ЦП (набор данных помещается в ОЗУ).
  • E1 также в основном привязан к ЦП, но с некоторыми промахами кеша в пуле буферов InnoDB, поэтому перед записью требуется выборка страницы с диска.
  • E3 — это смешанная рабочая нагрузка ЦП и ввода-вывода (больше промахов кеша в пуле буферов InnoDB, но все еще с достаточным количеством попаданий в кеш, чтобы получить хорошую пропускную способность фиксации).
  • E4 — это рабочая нагрузка, связанная с вводом-выводом (в основном промахи кеша).

Ослабление устойчивости рабочих нагрузок, привязанных к ЦП, приводит к значительному увеличению пропускной способности, но этого не происходит с рабочими нагрузками, связанными с вводом-выводом.

Теперь давайте сосредоточимся на параллельной репликации. Результаты стандартного ведомого устройства (SS-HD и SS-ND) обсуждать не стоит, так как они очень близки к результатам ведомого устройства с двоичными журналами (Obs1). сильный> выше). Мы также не будем обсуждать промежуточные основные результаты (IM-HD и IM-ND), поскольку они должны быть заменены серверами Binlog. Таким образом, все наблюдения ниже сделаны по результатам ведомого устройства с двоичными журналами (SB-HD и SB-ND):

  • Obs4: лучшее ускорение (~2,10) в E2 с высокой прочностью. Далее следует E1 с ускорением ~1,56 (всегда с высокой прочностью).
  • Obs5: ускорение для E4 скромное (~1,29), а результаты практически идентичны для обоих параметров долговечности.
  • Obs6: для E1 и E2 ускорение без долговечности практически отсутствует (менее 1,10).
  • Obs7: как для E1, так и для E2 снижение устойчивости с помощью однопоточной репликации приводит к более быстрому выполнению, чем включение параллельной репликации.
  • Obs8: результаты для E3 находятся на полпути между E1/E2 и E4: и SB-HD, и SB-ND получают небольшое ускорение от параллельного репликация (например, E4 и в отличие от E1/E2) и ослабление устойчивости заставляют вещи работать немного быстрее (например, E1/E2 и в отличие от E4), но не до такой степени, что однопоточная низкая надежность работает быстрее, чем многопоточная высокая надежность. .

Все эти наблюдения указывают на важность рабочей нагрузки при ускорении параллельной репликации:

  • Рабочие нагрузки, связанные с ЦП, похоже, получают небольшое ускорение в конфигурациях с высокой надежностью.
  • Ослабление устойчивости для рабочих нагрузок, связанных с ЦП, кажется лучшим вариантом, чем включение параллельной репликации в конфигурации с высокой устойчивостью.
  • Рабочие нагрузки, связанные с вводом-выводом, получают более ограниченное ускорение.

Наша первая реакция — разочарование: ускорение не такое высокое, как ожидалось. Не поймите нас неправильно: чем быстрее, тем лучше, особенно когда остается только обновить программное обеспечение, что мы все равно когда-нибудь сделаем. Однако наличие всего на 25 % больше операций записи на мастер (или 110 % в зависимости от того, какую среду мы рассматриваем) не поможет нам в долгосрочной перспективе. Параллельная репликация — это не решение (по крайней мере, не единственное), которое позволит нам остановить/избежать шардинга.

Идеи и будущая работа

У нас есть гипотеза, объясняющая небольшое ускорение: длительные транзакции. При наличии длительных транзакций параллельный конвейер репликации на подчиненном устройстве останавливается. Давайте возьмем следующие шесть транзакций, зафиксированных на мастере, в двух группах фиксации (B для начала и C для фиксации):

--------Time-------->
T1:  B-----------C
T2:           B--C
T3:           B--C
T4:           B--C
T5:              B--C
T6:              B--C

Выполнение этих транзакций на однопоточном ведомом устройстве занимает 33 единицы времени (шкала времени внизу):

----------------Time---------------->
T1:  B-----------C
T2:               B--C
T3:                   B--C
T4:                       B--C
T5:                           B--C
T6:                               B--C
              1         2         3
     123456789012345678901234567890123

Выполнение этих транзакций на многопоточном ведомом устройстве с SPT=4 занимает 17 единиц времени:

---------Time-------->
T1:  B-----------C
T2:  B-- . . . . C
T3:  B-- . . . . C
T4:  B-- . . . . C
T5:               B--C
T6:               B--C
              1
     12345678901234567

Таким образом, мы едва достигаем ускорения в 2 раза (а вторая группа коммитов даже не содержит большой транзакции). Низкое ускорение объясняется тем, что T1 намного больше, чем другие транзакции в группе. Итак, наша интуиция подсказывает, что для лучшего ускорения при параллельной репликации все транзакции должны быть одинакового размера, а более крупные транзакции должны быть разбиты на более мелкие (по возможности).

У нас есть много таких крупных транзакций в нашей рабочей нагрузке на Booking.com. Большинство наших вариантов дизайна предшествовало MySQL 5.6, где фиксация стоила дорого. Сокращение количества коммитов было хорошей оптимизацией в то время, поэтому делать много изменений в одной транзакции было хорошо. Теперь, с групповым коммитом бинарного лога, эта оптимизация менее полезна, но не вредит. Однако эта оптимизация очень плоха для параллельной репликации.

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

Вывод

Можно протестировать параллельную репликацию с реальной рабочей нагрузкой, даже если на главном сервере работает старая версия MySQL. Благодаря подчиненной группе в MariaDB 10.0 мы можем определить параллелизм на промежуточном мастере и включить параллельную репликацию на ведомом. Даже если эта идентификация параллелизма не так хороша, как на мастере, мы получаем приличные размеры групп.

Наши рабочие нагрузки, связанные с ЦП, получают ускорение от ~ 1,56 до ~ 2,10 с ограничениями высокой надежности. Это немного разочаровывает: нам бы хотелось, чтобы более двух ядер были заняты выполнением операций записи на ведомых устройствах. Мы предполагаем, что лучшего ускорения можно добиться, отслеживая крупные транзакции, но это еще нужно проверить. На данный момент и для данного типа рабочей нагрузки наши тесты показывают, что снижение устойчивости является лучшей оптимизацией, чем включение параллельной репликации. Наконец, с ослабленной устойчивостью параллельная репликация почти не показывает улучшений (улучшение от 4% до 6%), и до сих пор неизвестно, приведет ли отслеживание больших транзакций и их разделение к лучшему ускорению.

Наши рабочие нагрузки, связанные с вводом-выводом, получают ускорение с ~ 1,23 до ~ 1,29, что также разочаровывает, но ожидаемо, поскольку трудно бороться со временем поиска магнитных дисков. В этом типе рабочей нагрузки нестрогая настройка устойчивости выигрывает от параллельной репликации. Однако при достаточно высоком параллелизме на ведомом и для такого типа нагрузки расслаблять долговечность не очень выгодно. Трудно сказать, к каким улучшениям приведет поиск крупных транзакций для такого типа рабочей нагрузки.

Следующим шагом в оценке параллельной репликации будет попытка оптимистичной параллельной репликации. Это будет хорошая четвертая часть серии.

Хотели бы вы стать инженером в Booking.com? "Работать с нами"!