PostgreSQL streaming replication + repmgr: дешёвый HA без коммерческих лицензий
Настраиваем PostgreSQL streaming replication с hot standby и автоматическим failover через repmgr: standby читает production, переключение при падении мастера - ~30 секунд.
PostgreSQL streaming replication + hot standby как замена дорогим коммерческим HA-решениям
Когда клиент в феврале обозначил, что хочет уйти с Oracle SE на PostgreSQL, одним из первых вопросов стало: «а что с отказоустойчивостью?». Oracle SE без дорогих опций в этом месте слабоват - нормальный RAC стоит денег, которые и без того освобождаются при переходе. PostgreSQL предлагает streaming replication прямо из коробки. Мы разбирали это в плане миграции, а теперь дошли до практики.
Что мы настраивали
Стенд: мастер (CentOS 7, PostgreSQL 9.4) и один standby на отдельной машине в той же сети. Дополнительно - утилита repmgr от 2ndQuadrant для мониторинга состояния кластера и автоматического failover. Задача: standby должен читать production-нагрузку (аналитические запросы, отчёты), а при падении мастера переключиться с минимальным окном недоступности.
Streaming replication: механика
PostgreSQL пишет все изменения в WAL (Write-Ahead Log) перед применением к данным. Streaming replication - это когда standby подключается к мастеру как обычный клиент, но по специальному replication-протоколу, и получает поток WAL-записей в реальном времени, применяя их у себя.
Hot standby - режим в котором standby принимает SELECT-запросы прямо во время воспроизведения WAL. Это не отдельная фича поверх репликации, а встроенный режим работы: пока воспроизводится WAL, читать данные можно, но только те которые уже зафиксированы.
Настройка на мастере (postgresql.conf):
wal_level = hot_standby
max_wal_senders = 3
wal_keep_segments = 32
В pg_hba.conf добавляется строка, разрешающая replication-соединение с IP standby. На standby создаётся recovery.conf с указанием мастера:
standby_mode = on
primary_conninfo = 'host=master-ip port=5432 user=replicator password=...'
hot_standby = on
Запускаешь standby через pg_basebackup - он снимает консистентную копию с мастера и сразу ставит в режим ожидания. Если всё настроено, через несколько секунд видишь в логах standby: started streaming WAL from primary. Это приятный момент.
Лаг репликации видно через системное представление pg_stat_replication на мастере - там показывается задержка в байтах и времени между тем что записано на мастере и что уже применено на standby. На нашем стенде при умеренной write-нагрузке лаг держался в пределах секунды.
Hot standby и конфликты
Здесь есть нюанс который не сразу очевиден. WAL на мастере может содержать операции vacuum - очистку мёртвых строк. Если на standby в это время работает длинный SELECT, который держит снимок данных, и vacuum на мастере хочет убрать строки которые этот SELECT ещё «видит» - возникает конфликт репликации. PostgreSQL по умолчанию отменяет запрос на standby (max_standby_streaming_delay).
Для аналитических запросов которые могут работать долго это важно: нужно настроить max_standby_streaming_delay или hot_standby_feedback = on. Второй параметр говорит standby сообщать мастеру какой снимок данных сейчас активен - мастер учитывает это при vacuum. Есть обратная сторона: раздувание таблиц на мастере если standby держит длинные транзакции. Мы остановились на hot_standby_feedback = on и следим за bloat мастера.
repmgr: автоматический failover
Репликация сама по себе не делает failover. Если мастер упал - standby продолжает воспроизводить WAL из буфера, потом ждёт. Клиенты получают ошибки соединения. Нужен кто-то кто заметит отказ и переключит standby в режим мастера.
repmgr - утилита именно для этого. Устанавливается на оба сервера, в конфиге описывается топология кластера. Демон repmgrd мониторит состояние мастера: периодически коннектится и проверяет доступность. При недоступности - инициирует промоушн standby.
Команда промоушна вручную выглядит просто:
repmgr standby promote
После неё standby переходит в режим мастера - PostgreSQL переходит в read-write, создаёт новый timeline в WAL. Клиентам нужно переподключиться к новому мастеру. Автоматически это делает repmgrd: при обнаружении отказа мастера он выполняет промоушн и уведомляет (через скрипт, который мы написали) систему мониторинга и меняет запись в конфигурации балансировщика.
На практике мы несколько раз имитировали падение мастера через kill -9 процесса PostgreSQL. repmgrd обнаруживал проблему примерно за 15-20 секунд (зависит от reconnect_attempts и reconnect_interval), промоушн занимал ещё несколько секунд. Итого от момента гибели мастера до появления нового читаемого и пишущего PostgreSQL - около 30 секунд.
Это не нулевое RTO, но для большинства задач DWH вполне приемлемо. Сравните с ценником Oracle Data Guard.
Что с обратным восстановлением старого мастера
Это отдельная операция, которую repmgr тоже поддерживает: repmgr standby clone - старый мастер клонируется с нового мастера и подключается как standby нового кластера. Потом можно при необходимости сделать обратный switchover. Мы проверили - работает, но требует внимательности: timeline в WAL сменился, и старый мастер должен синхронизировать историю с нового.
Нагрузка на standby
Аналитические запросы с отчётностью мы направили на standby через изменение строки подключения в reporting-инструменте. Нагрузка - SELECT-ы к витринам, несколько параллельных сессий. Standby держит нормально: WAL-лаг от этого не растёт, производительность запросов сопоставима с мастером (те же данные, тот же планировщик).
Единственное ограничение: нельзя создавать временные таблицы при hot_standby_feedback = on на старых версиях - в 9.4 это починили. Мы писали о 9.4 в январе, там же про другие улучшения для аналитики.
Итог
Streaming replication + hot standby в PostgreSQL 9.4 - рабочий HA без коммерческих надстроек. repmgr добавляет автоматический failover и управление топологией. Настройка занимает день, включая тестирование отказовых сценариев.
Основные грабли:
- Конфликты репликации при длинных SELECT на standby - решается
hot_standby_feedback, но надо следить за bloat. - Failover не мгновенный - около 30 секунд, что нужно учитывать в SLA.
- Обратный switchover требует ручного клонирования старого мастера.
Для задач DWH и аналитики схема «мастер + читающий standby с автофайловером» закрывает основные требования без Oracle-ценника.