Как добиться отказоустойчивости в PostgreSQL

«Как добиться отказоустойчивости в PostgreSQL» — вопрос из категории Базы данных, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Типичная архитектура HA-кластера: Я предпочитаю использовать Patroni в связке с etcd (или ZooKeeper) как дистрибьютированное хранилище конфигурации (DCS). Это решение автоматизирует failover, переконфигурацию и предотвращает split-brain.

Состав кластера (минимум 3 ноды):

  1. PostgreSQL + Patroni на каждой ноде.
  2. etcd-кластер (отдельно или co-located) из 3 или 5 нод для кворума.

Как это работает:

  • Patroni на каждой ноде управляет экземпляром PostgreSQL и через etcd координирует выбор лидера (мастера).
  • Только мастер принимает запись. Реплики работают в режиме потоковой репликации (streaming replication).
  • При падении мастера Patroni автоматически проводит выборы и promotes одну из синхронных реплик в нового мастера. Остальные реплики переключаются на него.

Конфигурация (упрощённо):

# Фрагмент конфига Patroni (patroni.yml)
scope: my-postgres-cluster
namespace: /service/
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 10.0.1.1:8008

etcd:
  hosts: 10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    postgresql:
      use_pg_rewind: true
      parameters:
        wal_level: replica
        hot_standby: "on"
        max_wal_senders: 10
        wal_keep_size: 1GB

Для подключения приложений:

  • Использую HAProxy или PgBouncer в режиме transaction pooling перед кластером. Они получают от Patroni статус нод (через REST API /primary или /read-only) и направляют write-запросы на текущего мастера, а read-запросы — на реплики.
  • В DNS или строке подключения приложения указываю адрес балансировщика, а не конкретную ноду БД.

Резервное копирование: Отказоустойчивость — не замена бэкапам. Параллельно настраиваю pg_basebackup и WAL-архивацию в объектное хранилище (S3) с помощью pgBackRest или WAL-G для возможности Point-in-Time Recovery (PITR).