Перейти к содержанию
Innovialabs

Как настроить потоковую репликацию в PostgreSQL

Продвинутое4 мин

Коротко

Разрешите репликацию на primary, создайте роль и слот, разверните standby через pg_basebackup с флагом -R, следите за отставанием в pg_stat_replication, а переключение делайте через pg_promote или автоматически с Patroni.

Короткий ответ

Потоковая репликация передаёт журнал предзаписи (WAL) с основного сервера (primary) на один или несколько standby почти в реальном времени. Standby можно использовать для чтения и как готовую замену при аварии.

Порядок настройки:

  1. Разрешить подключения для репликации на primary.
  2. Создать роль и слот репликации.
  3. Скопировать данные на standby через pg_basebackup.
  4. Запустить standby и проверить отставание.
  5. Продумать маршрутизацию чтения и сценарий failover.

Важно: репликация — это не резервная копия. Ошибочный DELETE мгновенно уедет на все реплики, поэтому бэкапы с point-in-time recovery нужны всё равно.

Шаг 1. Настройка primary

В postgresql.conf:

listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10

wal_level = replica — значение по умолчанию в современных версиях, но его стоит проверить. Изменение listen_addresses и wal_level требует перезапуска.

Создайте роль для репликации и слот:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'сложный_пароль';
SELECT pg_create_physical_replication_slot('standby1');

Разрешите подключение в pg_hba.conf только с адреса реплики:

host  replication  replicator  10.0.0.12/32  scram-sha-256

После правки pg_hba.conf достаточно SELECT pg_reload_conf();.

Шаг 2. Развёртывание standby

На сервере реплики остановите PostgreSQL и очистите каталог данных. Затем скопируйте данные с primary:

pg_basebackup -h 10.0.0.11 -U replicator \
  -D /var/lib/postgresql/data \
  -X stream -S standby1 -R -P
  • -X stream — передавать WAL во время копирования;
  • -S standby1 — использовать созданный слот;
  • -R — создать файл standby.signal и записать primary_conninfo в postgresql.auto.conf.

Проверьте, что в postgresql.auto.conf есть primary_slot_name = 'standby1', и запустите сервер. Параметр hot_standby = on (по умолчанию) разрешает читать с реплики.

Зачем нужны слоты и чем они опасны

Слот репликации заставляет primary хранить WAL, пока standby его не получит. Без слота реплика после долгого простоя может отстать безвозвратно и потребует новой копии.

Обратная сторона: если реплика выключена навсегда, а слот остался, WAL копится на primary до заполнения диска. Поэтому:

  • удаляйте слоты выведенных реплик: SELECT pg_drop_replication_slot('standby1');;
  • ограничьте объём через max_slot_wal_keep_size (доступен в современных версиях);
  • мониторьте размер удерживаемого WAL.

Шаг 3. Мониторинг отставания

На primary:

SELECT client_addr, state, replay_lag,
       pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication;

SELECT slot_name, active,
       pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS retained_bytes
FROM pg_replication_slots;

На standby — время с последней применённой транзакции:

SELECT now() - pg_last_xact_replay_timestamp() AS replay_delay;

Этот показатель растёт и при отсутствии записей на primary, поэтому оценивайте его вместе с lag_bytes. Выведите метрики в систему мониторинга (например, Prometheus с postgres_exporter) и настройте алерты на отставание, неактивные слоты и отключение реплики.

Шаг 4. Чтение с реплик

Реплики разгружают primary от отчётов, аналитики и тяжёлых выборок. Варианты маршрутизации:

  • в приложении — два пула подключений: запись на primary, чтение на реплику;
  • через libpq — несколько хостов в строке подключения и параметр target_session_attrs (read-write для записи, read-only или prefer-standby в новых версиях);
  • через прокси — HAProxy или Pgpool-II.

Помните про асинхронность: только что записанные данные могут ещё не появиться на реплике. Чтение «своих» изменений (например, сразу после сохранения формы) направляйте на primary. Если потеря последних транзакций при аварии недопустима, рассмотрите синхронную репликацию через synchronous_standby_names — ценой задержки записи.

Шаг 5. Failover

Вручную

  1. Убедитесь, что primary действительно недоступен, и изолируйте его, чтобы он не вернулся как второй primary (split-brain).
  2. На standby выполните SELECT pg_promote(); или pg_ctl promote.
  3. Переключите приложение: DNS, виртуальный IP или строку подключения.
  4. Старый primary верните только как реплику — через pg_rewind или новый pg_basebackup.

С Patroni

Patroni управляет кластером автоматически: хранит информацию о лидере в DCS (etcd, Consul или ZooKeeper), следит за здоровьем узлов и при аварии продвигает лучшую реплику. Перед кластером обычно ставят HAProxy, который проверяет REST API Patroni (эндпоинты /primary и /replica) и направляет трафик на нужный узел.

Полезные команды:

patronictl -c /etc/patroni.yml list
patronictl -c /etc/patroni.yml switchover

Плановый switchover регулярно проверяйте на тестовом стенде — failover, который ни разу не запускали, нельзя считать рабочим. Подробности в документации PostgreSQL.

Частые вопросы

Для отказоустойчивости минимум одна, для автоматического failover с Patroni обычно берут три узла PostgreSQL и кластер DCS из трёх узлов, чтобы был кворум. Дополнительные реплики добавляют под нагрузку на чтение.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.