Мифы и реалии «Мультимастера» в архитектуре СУБД PostgreSQL. Часть. 3

Привет, Хабр! Это снова мы — Павел Конотопов (@kakoka) и Михаил Жилин (@mizhka), сотрудники компании Postgres Professional. Напомню, что Павел занимается архитектурой построения отказоустойчивых кластеров, а я анализом производительности СУБД. У каждого из нас за плечами более десяти лет опыта в своей области.

Во второй части статьи »Мифы и реалии «Мультимастера» в архитектуре СУБД PostgreSQL» мы говорили о гарантии согласованности данных и разрешение конфликтов. Разобрали как выявлять и разрешать конфликты, используя разные способы. Теперь пришла пора одной из самых важных характеристик хранения данных — надёжности.

Часть 3. Производительность: почему Мультимастер замедляет транзакции?

И вот мы подошли к самому вкусному — к производительности. Всё, что было сказано выше — хорошие и надёжные механизмы по обеспечению консистентности данных и разрешению конфликтов. Однако любые механизмы по обеспечению надёжности, как известно, отражаются на производительности.

Описав механизм глобального коммита, разрешения конфликтов, возникают вопросы: «Насколько всё это быстро происходит?», «Где стоит применить «Мультимастер?», потому что он точно не про «скорость без границ».

Представим, что к нам пришел заказчик с требованиями:

  • необходим кластер «Мультимастера» из двух или трёх узлов;

  • кластер предназначен OLTP-процессингу;

  • закрытая модель нагрузки в десятки параллельных потоков;

  • требования к средней задержке фиксации транзакции (commit average latency) — 300 мс;

  • транзакционная нагрузка — процессинг JSON-файлов, размер каждого около 20 Мб.

В первых тестах с «Мультимастера» для этой задачи результат был катастрофически медленным, всё работало в 3–4 раза медленнее по сравнению с одиночным экземпляром СУБД:

  • «Мультимастер», 3 узла — 800 мс;

  • Postgres Pro Enterprise, 1 узел — 250 мс;

Заказчик выразил мнение, что такая низкая скорость — из-за надёжности «Мультимастера» и его супер возможностей. «Да ваш «Мультимастер» — просто черепаха!» — сказал нам заказчик. И мы пошли разбираться, где же он притормаживает.

Почему может тормозить «Мультимастер»?

Настройка объёма информации, записываемой в WAL-журналы. При включении дополнительного уровня логирования данных в WAL-файлы с информацией для логического декодирования, получили замедление в три раза. Хотя при таком уровне логирования в журналы добавляется всего пара записей, и WAL-файлы не раздуваются в размерах.

Проигрывание изменений на всех узлах. Изменения данных с первого узла применяются на втором узле, а следом применяются и на третьем. Но на третьем узле мы применим изменения за то же время, да и изменения на обоих узлах применяются параллельно. Откуда возникло замедление в 3 раза?

Глобальный коммит. Все узлы при применении изменений должны проголосовать по протоколу PAXOS, договориться о согласованном применении изменений: это требует дополнительные временные затраты, но они невелики.

В ходе разбирательства нашлись проблемы как в настройках «Мультимастера», так и в способах работы с ним со стороны приложения.

Проблема №1. Таблицы без Primary Key

Если на узел кластера приходит строка изменения без первичного ключа, то приходится делать полное сканирование таблицы и искать, в какой строке появились изменения. В «Мультимастере» Postgres Pro естьспециальная настройка: если есть таблицы без первичного ключа, то их можно игнорировать. Тогда они будут реплицироваться: multimaster.ignore_tables_without_pk.

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

Проблема №2. Время фиксации при глобальном коммите

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

653e3617a4d31b717b913618d5f53e12.jpg

Просмотрели информацию о нескольких транзакциях: везде одна и та же картина. Поинтересовались у разработчиков, что именно фиксируется в транзакциях. Логично было собирать небольшие изменения JSON (пусть и размером в 20 Мб) в «пачку» и фиксировать их одним коммитом. Оказалось, что на стороне Java-приложения был включен автокоммит, то есть каждая DML-операция создавала распределённый глобальный коммит. После рекомендации выключить автокоммит, ситуация нормализовалась:

178dd956bb68835063800d376ed40657.jpg

«Мультимастер» стал работать очень быстро, время глобального коммита резко сократилось и стало занимать не 99% времени от всей транзакции, а всего лишь 28%, а это уже сравнимо с работой обычной физической репликации.

Проблема №3. Производительность сети виртуальной машины

Кластер «Мультимастера» был развёрнут в среде виртуализации. У виртуальной машины QEMU был виртуальный сетевой интерфейс virtio-net-pci, драйвер которого по умолчанию работает в однопоточном (или одноочередном) режиме.

Чтобы глобальный коммит происходил быстро, требуется, чтобы сеть отвечала практически мгновенно. Скорость глобального коммита при решении Проблемы №2 хоть и уменьшилась, но так и не достигла требуемых значений. При дальнейших исследованиях причин мы заметили, что скорость коммита зависит от производительности сетевого устройства. Мы переключили драйвер virtio-net-pci в многопоточный (многоочередный) режим, включили multiqueue на всех узлах кластера и выставили количество очередей в значение 4. После этих манипуляций время выполнения коммита уменьшилось и достигло требуемых заказчиком значений. 

Аварийное нарушение работы логической репликации

В кластере «Мультимастера» произошла аварийная ситуация. Общую картину может дать фрагмент журнала работы сервера (отредактирован и сокращен для лучшего понимания):

14:52:07 — нарушение работы логической репликации, «узел-2» не забирает изменения от «узла-1»

15:48:52 — диск pg_wal на «узле-1» полностью заполняется WAL-файлами и уходит в перезагрузку

15:49:28 — «узел-1» запускается и переходит в catchup. Рабочая нагрузка переходит на «узел-2»

16:29:50 — диск pg_wal на «узле-2» полностью заполняется WAL-файлами

В один прекрасный момент логическая репликация, которая выбирала данные для узла-2, перестала работать. Причина: на стороне приёмника «узла-2» что-то пошло не так. На «узле-1» начали копиться WAL-файлы. Они копились до тех пор, пока дисковое пространство выделенное под хранение WAL-файлов, не закончилось. Как только оно закончилось, «узел-1» ушёл в перезагрузку, а затем перешёл в режим восстановления. «Узел-2» ждёт, когда «узел-1» вернётся в нормальное состояние и тоже накапливает WAL-файлы для этого узла. Накапливает он их до тех пор, пока и у него не заканчивается дисковое пространство — так весь кластер «Мультимастера» перешёл в неработоспособное состояние.

У этой проблемы есть довольно простое решение: в PostgreSQL есть настройка, с помощью которой можно указать, какое количество WAL-файлов необходимо хранить до того момента, пока слот репликации не остановится: max_slot_wal_keep_size — ограничение размера слотов репликации. Если вдруг WAL-файлов накопилось больше указанного размера, то следует найти слот, который заставляет держать WAL-файлы, и удалить его. Пусть лучше остановится работа логической репликации, но «Мультимастер» продолжит работать. Поэтому ограничиваем размер хранимых WAL-файлов, предотвращая возможное возникновение аварийной ситуации. Теперь обратимся к вопросу производительности.

Производительность: рекомендации

Чтобы добиться производительности «Мультимастера» можно применить следующие рекомендации:

  • обязательно наличие первичного ключа (primary key) на реплицируемых таблицах;

  • делать более объемные транзакции, чтобы глобальный коммит стал «дешевле». Чем объёмнее транзакция — тем меньше время её фиксации (commit);

  • настроить сеть виртуальных машин под требуемую сетевую нагрузку;

  • выставить max_slot_wal_keep_size, чтобы кластер «Мультимастера» не уходил в отказ из-за переполнения диска.

Дополнительно можно принять во внимание такие замечания:

Стремитесь избегать конфликтов на уровне кода на разных узлах: разрешение конфликтов — «дорогая» операция. Какой способ разрешения будет выбран, настолько «дорогим» и долгим будет время этой операции.

Синхронизируйте время на узлах кластера. «Мультимастер» использует глобальные распределенные коммиты, построенные на протоколе распределённого консенсуса PAXOS. Этот консенсус использует временные метки. Время должно быть синхронизировано с одним источником времени на всех узлах кластера. Если будет расхождение времени на узлах, то возникнут дополнительные задержки при фиксации транзакций, что сильно снижает производительность.

Внимательно отнеситесь к требованиям со стороны службы безопасности. Антивирус отслеживает сетевую активность между узлами кластера и изменения в каталоге БД, auditd-правила следят за бинарными файлами экземпляра СУБД. Эта активность со стороны ПО, обеспечивающего безопасность, всегда отражается на производительности СУБД, и не в лучшую сторону. Одним из требований со стороны ДБА к службе ИБ может быть исключение сетевой активности внутри кластерного трафика и каталога БД из области наблюдения средств безопасности. 

Крупные миграции данных следует делить на части. Если у вас есть огромная миграция (сотни, а то и тысячи миллиардов строчек), то постарайтесь разделить её на части. Когда вы сделаете одну большую транзакцию, её нужно потом логически декодировать в памяти: это зачастую приводит к срабатыванию OOM-киллера или повышенной нагрузке на все узлы кластера.

Итоги

Сначала о том, чем закончился реальный кейс с заказчиком: время транзакции упало с 800 мс до 300 мс, система успешно прошла все тесты и перешла в промышленную эксплуатацию. Мы получили ценный опыт и знаем теперь, какие настройки надо обязательно сделать сразу, чтобы кластер «Мультимастера» работал стабильно.

Исходные показатели производительности:

  • Фиксация транзакций в кластере «Мультимастер» — 800 мс;

  • Фиксация транзакций в одиночном экземпляре Postgres Pro Enterprise —250 мс.

Достигнутые результаты:

  • Фиксация транзакций в кластере «Мультимастер» — 300–350 мс;

  • Система в промышленной эксплуатации на Postgres Pro Enterprise Multimaster;

  • Все приобрели ценный опыт.

Подведем итоги нашей статьи. В начале нее мы говорили о мифах «Мультимастера». Напомним, что «Мультимастер»:

  • не про масштабирование записи, но масштабирование чтения;

  • не про пиковую производительность, но для нагруженных систем;

  • не про надёжность;

  • не про доступность;

  • не для промышленного применения.

В итоге можно уверенно утверждать, что реальность «Мультимастера» (от Postgres Pro):

  • не про масштабирование записи, а про масштабирование чтения;

  • не про пиковую производительность, а для нагруженных систем;

  • не про надёжность надежен;

  • не про доступность уровень доступности может достигать 99,99*%;

  • не для промышленного применения проверенное промышленное решение.

Реализация технологии «Мультимастер» в Postgres Pro Enterprise позволяет добиться высокой доступности («AlwaysOn» архитектура, база данных доступна всегда). Период недоступности классического кластерного ПО («Active-Passive» архитектура) можно рассчитать, как сумму времён, затраченных на определение кластерным ПО сбоя мастер-узла, выборы нового мастера, переключение роли выбранного узла, перенастройку (пусть и автоматическую), TCP-прокси, переподключение приложения к новому «мастеру».

В кластере «Мультимастера» приложение просто подключится к другому узлу кластера. Время на такое переподключение может отличаться на один-два порядка в меньшую сторону от времени переподключения при использовании классического кластерного решения.

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

Решения на базе «Мультимастера» уже внедрены в промышленную эксплуатацию весьма серьезными заказчиками (рассказали бы, но, увы, вынуждены соблюдать NDA). Кластер «Мультимастера» уверенно можно использовать в промышленных решениях!

Материалы для изучения

«Мультимастер» последней версии — проверенное решение, которое можно использовать в продуктиве. Раньше мы упоминали, что Postgres Pro Multimaster — продукт с закрытым кодом, но это не значит, что прежде чем решить, нужен он вам или нет, вы не можете о нем ничего узнать.

Для изучения технологии и ее реализации есть:

Вы можете загрузить себе учебную виртуальную машину, запустить «Мультимастер» и попробовать всё, о чём мы рассказали в данной статье. Кроме того, Postgres Pro Enterprise может быть выдан и бесплатно для тестирования (необходимо связаться с отделом продаж компании).

Материалы для более вдумчивого изучения технологии «Мультимастер» и связанными с ней темами:

© Habrahabr.ru