Настройка PostgreSQL высокой доступности через PgPool-II

Простой узла базы данных останавливает продажи и поддержку: клиенты уходят, а команда вручную восстанавливает работу. Мы настраиваем отказоустойчивый кластер под ключ — база переживает отказ сервера без потери данных, переключение занимает секунды, время простоя сокращается в разы.
Часто задаваемые вопросы

PgPool-II: что ломается при отказе узла базы данных

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

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

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

Но присутствие PgPool-II в схеме само по себе не убирает точку отказа. Если он запущен в одном экземпляре, без резервирования самого пула и без выверенных таймаутов проверки, отказ просто переезжает с базы на него. Ниже разбираем, как это закрывается.

Что даёт отказоустойчивый кластер баз данных

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

Приложение подключается к одному адресу, а PgPool-II распределяет входящие соединения между серверами. Проверка доступности идёт с коротким интервалом: после нескольких неудачных откликов узел исключается из выдачи, оставшиеся принимают его трафик. Ошибок соединения на стороне приложения нет — меняется только внутренняя маршрутизация, а время восстановления измеряется секундами вместо ручного разбора.

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

Предсказуемость здесь важнее пиковой производительности. Деградация одного узла превращается в событие с известным сценарием: часть запросов замедляется, но сервис остаётся доступным. Класс отказов «упал сервер — лежит весь продукт» уходит из перечня рисков, а поведение кластера проверяется на учениях, а не выясняется в момент реальной аварии.

Режимы работы PgPool-II и их ограничения

Отказоустойчивый контур на PgPool-II собирают несколькими способами, и балансировщик нужен не всегда. Ключевой вопрос — что именно требуется: переживать отказ основного узла, распределять читающую нагрузку или гасить всплески коротких подключений. От этого зависит, где встанет PostgreSQL, а где — промежуточный слой.

Вариант Когда подходит Ограничения
Потоковая репликация горячего резерва без балансировщика Один основной узел и резерв, чтение с резерва, переключение по регламенту Автоматического переключения при отказе нет; адреса узлов прописаны в конфигурации приложения
PgPool-II в режиме репликации запросов Единый адрес для приложения и автоматическое переключение при отказе Без сторожевого модуля возможно расщепление кластера при обрыве связи; чтение с реплик отстаёт
PgPool-II как балансировщик соединений Много коротких подключений, всплески, жёсткий лимит соединений на сервере Отказоустойчивости не даёт — только удержание и перераспределение соединений
Логическая репликация выборочных таблиц Перенос между мажорными версиями, вынос части данных на отдельный контур Нет автоматического переключения, задержка выше, состав объектов должен совпадать

Что проверить перед выбором

Режим репликации запросов не снимает ограничений самой СУБД: запросы, чувствительные к актуальности данных, маршрутизируются на основной узел, а расширения должны стоять на всех узлах. Совместимость проверяют на пиковой нагрузке — задержку репликации, поведение при обрыве канала и корректный возврат старого основного узла в строй.

Как мы внедряем отказоустойчивый кластер: этапы работ

Кластер высокой доступности собирается не «на живую», а по последовательности, где каждый шаг подтверждается проверкой. Ниже — порядок работ, по которому мы ведём проект: от аудита до передачи смене заказчика. На каждом этапе видно, что уже сделано, чем это проверено и какие риски остались открытыми.

  1. Аудит текущей схемы и точек отказа. Разбираем контур как есть: где проходит запись, кто держит соединения, как устроена репликация. Выписываем единые точки — один узел записи, балансировщик без резерва, ручной перевод при сбое — и оцениваем цену простоя каждой.
  2. Проектирование контура. Фиксируем роли узлов (ведущий, резервный, узлы чтения), схему потоков данных между PgPool-II, серверами баз и приложениями, правила маршрутизации запросов на чтение и запись, режим распределения нагрузки.
  3. Настройка узлов и проверка переключения. Поднимаем пул соединений, репликацию, проверки живости и автоматическое переключение ролей. Отдельно проверяем, что приложение переживает смену ведущего узла без правок в коде.
  4. Испытания отказом на стенде. По очереди выводим из строя каждый узел и связь между площадками: смотрим время переключения, поведение очереди запросов и то, какие транзакции теряются, а какие нет.
  5. Прогон под нагрузкой. Подаём профиль, близкий к рабочему: пиковые соединения, тяжёлые отчёты, длинные транзакции. Проверяем, что переключение укладывается в согласованное окно и под нагрузкой.
  6. Передача в эксплуатацию и обучение смены. Отдаём конфигурации, схему ролей и потоков, регламент переключения и разбора сбоев. Проводим учения со сменой заказчика, чтобы перевод узлов делался по инструкции, а не по памяти.

Конфигурации, схемы и регламенты: артефакты внедрения

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

  • Рабочие конфигурации отказоустойчивого контура — файлы PgPool-II, узлов репликации и менеджера кластера с параметрами под ваш профиль нагрузки, а не демонстрационные. Хранятся под контролем версий, чтобы настройку можно было откатить, а не восстанавливать по памяти.
  • Схема контура — актуальная топология: роли узлов, маршруты трафика, точки отказа и порядок их прохождения. Обновляется при каждом изменении, а не живёт в голове одного инженера.
  • Правила доступа и роли — матрица прав на узлы, режимные функции балансировщика и мониторинг; отдельные учётки для дежурного и для автоматизации, разделение чтения и изменения.
  • Регламент переключения — пошаговый сценарий планового и аварийного перевода ролей, с ожидаемым временем, критериями «пора вмешиваться» и порядком возврата узлов в строй.
  • Инструкция по восстановлению узла — что делать при отставании или выпадении реплики: проверка синхронности, условия догона без полного пересоздания, команды для типовых сбоев.
  • Наблюдаемость и оповещения о сбоях — набор метрик (отставание реплик, состояние узлов, доля ошибок маршрутизации) с порогами, при которых дежурный получает сигнал, а не узнаёт о сбое из жалоб.
  • Записи учений — фактическое время восстановления по итогам тренировок и список правок, внесённых в регламент после каждой.

Кейс: простой при отказе узла сократился в разы

Исходная схема и её слабые места

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

Что изменили и что показали метрики

Перед кластером поставили PgPool-II: он держит пул соединений, периодически опрашивает узлы и сам инициирует переключение на резерв, когда основной перестаёт отвечать. Доля автоматических переключений выросла с нуля почти до всех отказов, которые фиксирует мониторинг; ручной разбор остался только для сценариев с потерей сети между узлами, где нужно осознанное решение.

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

Чем отличается балансировка соединений от репликации

Репликация и балансировка решают разные задачи, и путать их дорого. Репликация отвечает за то, чтобы копия данных существовала на другом узле: основной узел передаёт изменения потоком, резервный применяет их и доступен только на чтение. Балансировка отвечает за маршрут запроса — на какой узел он уйдёт и что произойдёт с ним в момент отказа.

Настроив потоковую репликацию, нагрузку чтения вы не распределите. Реплика получает те же данные, но приложение обращается к основному узлу, пока между ним и базами нет маршрутизатора. PgPool-II работает здесь: разбирает запрос, изменения отправляет на основной узел, чтение раскладывает по репликам и держит пул соединений.

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

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

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

Технические сомнения перед внедрением: разбор

Перед внедрением PgPool-II у команды всплывают одни и те же сомнения: придётся ли править приложение, нужен ли простой, сработает ли автоматическое переключение, что делать при расхождении данных.

Приложение придётся переписывать?

Нет. PgPool-II встаёт между приложением и кластером и говорит на том же протоколе, что обычный сервер баз данных. Меняется только строка подключения — драйверы и библиотеки доступа к данным продолжают работать. Точечно проверяем запросы, завязанные на одном узле: последовательности и серверные курсоры.

Внедрение на работающем кластере — это простой?

Простой не нужен. PgPool-II поднимается рядом с текущим кластером; сначала переводим на него чтение и смотрим поведение под нагрузкой, запись — последней. На это нужна пауза в секунды, чтобы закрылись открытые транзакции. Откат — возврат приложений на прежнюю строку подключения.

Как проверить автоматическое переключение?

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

Что будет при расхождении данных?

PgPool-II следит за отставанием реплик: при превышении порога узел исключается из выдачи чтения — приложение не получает устаревшие данные. Узел, выпавший после сбоя, пересобирается из копии основного. Задержка репликации, доступность и смена роли выводятся на панель мониторинга: алерт приходит раньше, чем проблему заметят пользователи.

Обсудим задачу и вернёмся с планом работ

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

От заказчика нужно немногое:

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

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

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139