У вас PostgreSQL 14 на единственном сервере? При отказе сервера сайт недоступен, а ручное переключение на реплику занимает 30–60 минут. Мы автоматизируем failover, сокращая RTO до 10–30 секунд. Наш опыт — 5+ лет и 50+ проектов по PostgreSQL и MySQL High Availability. В этой статье разбираем реальные конфигурации Patroni, etcd, InnoDB Cluster и HAProxy.
Проблема в том, что большинство администраторов настраивают асинхронную репликацию без автоматического обнаружения отказов. Это приводит к потере данных (RPO > 0) и длительным простоям. Синхронная репликация и автоматический failover — единственный способ достичь RTO < 30 секунд и RPO = 0. Мы предлагаем готовые решения на основе Patroni для PostgreSQL и InnoDB Cluster для MySQL, проверенные в production с нагрузкой до 100 000 запросов в секунду.
Почему автоматический failover критичен для базы данных?
Отметим: когда мастер-сервер базы данных падает, сайт или приложение становятся недоступны. Ручное переключение на реплику занимает часы, особенно если администратор не на месте. Мы настраиваем автоматический failover, который снижает RTO с десятков минут до 10–30 секунд. На одном из проектов мы мигрировали кластер PostgreSQL 12 на Patroni: RTO снизился с 25 минут до 15 секунд, а количество инцидентов уменьшилось на 95%.
Какие проблемы решаем
- Потеря данных при сбое: без синхронной репликации часть транзакций может быть потеряна. Мы настраиваем synchronous режим для нулевых потерь.
- Долгое восстановление: ручное повышение реплики — до 30 минут. Автоматизация сокращает до секунд.
- Неопределённость лидера: без координации несколько реплик могут считать себя мастером (split-brain). Используем etcd для консенсуса.
Как Patroni и etcd обеспечивают консистентность?
Patroni — стандарт de facto для PostgreSQL
Patroni — Python-демон, работающий на каждом узле. Он использует DCS (Distributed Consensus Store) для выбора лидера. Подробности — в документации Patroni. Конфигурация на каждом узле:
# /etc/patroni/patroni.yml
scope: production-cluster
namespace: /service/
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.10:8008
etcd3:
hosts: 192.168.1.20:2379,192.168.1.21:2379,192.168.1.22:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 30
maximum_lag_on_failover: 1048576 # 1MB
synchronous_mode: false
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.10:5432
data_dir: /var/lib/postgresql/14/main
authentication:
replication:
username: replication
password: replication_password
superuser:
username: postgres
password: postgres_password
parameters:
max_connections: 200
shared_buffers: 256MB
wal_level: replica
hot_standby: on
wal_log_hints: on
tags:
nofailover: false
noloadbalance: false
HAProxy для прозрачного переключения
Patroni предоставляет healthcheck endpoints /master и /replica. HAProxy направляет запись на мастер, чтение — на реплики:
# haproxy.cfg
frontend postgres_write
bind *:5000
default_backend postgres_master
frontend postgres_read
bind *:5001
default_backend postgres_replicas
backend postgres_master
option httpchk GET /master
http-check expect status 200
server node1 192.168.1.10:5432 check port 8008 inter 2s fall 3 rise 2
server node2 192.168.1.11:5432 check port 8008 inter 2s fall 3 rise 2
server node3 192.168.1.12:5432 check port 8008 inter 2s fall 3 rise 2
backend postgres_replicas
balance leastconn
option httpchk GET /replica
http-check expect status 200
server node1 192.168.1.10:5432 check port 8008 inter 2s fall 3 rise 2
server node2 192.168.1.11:5432 check port 8008 inter 2s fall 3 rise 2
server node3 192.168.1.12:5432 check port 8008 inter 2s fall 3 rise 2
MySQL: InnoDB Cluster и MySQL Router
Для MySQL используем Group Replication + MySQL Router. Инициализация кластера:
mysqlsh [email protected]:3306
JS> dba.createCluster('myCluster')
JS> cluster = dba.getCluster()
JS> cluster.addInstance('[email protected]:3306')
JS> cluster.addInstance('[email protected]:3306')
JS> cluster.status()
Router автоматически направляет запись на primary.
Сравнение решений
| Параметр | Patroni + etcd | InnoDB Cluster |
|---|---|---|
| СУБД | PostgreSQL | MySQL |
| Механизм координации | etcd/Consul/ZooKeeper | Paxos (Group Replication) |
| RTO | 10–30 сек | 5–15 сек |
| RPO (синхронный режим) | 0 | 0 |
| Сложность настройки | Средняя | Низкая (встроено) |
Patroni превосходит ручной failover в 100 раз по скорости восстановления. InnoDB Cluster выигрывает в простоте.
Сценарии отказов и автоматическая реакция
| Сценарий | Действие Patroni | Время реакции |
|---|---|---|
| Отказ мастера (crash) | Автоматическое голосование, повышение реплики с минимальным лагом | 10–30 с |
| Сетевая недоступность мастера | etcd теряет lease, инициируется failover | 30–60 с (TTL) |
| Падение процесса PostgreSQL | Patroni перезапускает PostgreSQL или инициирует switchover | 5–10 с |
| Плановая замена мастера | patronictl switchover без даунтайма |
5–10 с |
Процесс работы
- Аналитика: инвентаризация текущей инфраструктуры, выбор топологии (Patroni/InnoDB Cluster).
- Проектирование: схема кластера, расчёт ресурсов (CPU, RAM, диск).
- Реализация: развёртывание DCS, настройка репликации, конфигурация балансировщика.
- Тестирование: симуляция отказов, замеры RTO, проверка консистентности.
- Деплой: ввод в эксплуатацию, обучение команды, документация.
Что входит в работу
- Конфигурация кластера (Patroni или InnoDB Cluster)
- Настройка etcd/Consul (для PostgreSQL)
- Интеграция с HAProxy или MySQL Router
- Мониторинг (Prometheus + Grafana)
- Документация по аварийному восстановлению
- Обучение дежурной смены
- Поддержка 30 дней после запуска
Сроки и стоимость
Настройка failover-кластера — от 3 до 5 рабочих дней. Стоимость рассчитывается индивидуально в зависимости от сложности архитектуры. Гарантируем RTO не более 30 секунд. Получите консультацию — мы оценим ваш проект за 1 день.
Типичные ошибки при настройке
- Не настроены healthcheck-эндпоинты — HAProxy не видит смену лидера.
- Слишком большой
maximum_lag_on_failover— поднимается устаревшая реплика. - Отсутствие post-failover скриптов — приложение подключается к старому хосту.
Как тестировать failover без простоя
Мы всегда тестируем на копии продакшена. Команда patronictl failover --force имитирует отказ. Замеряем время недоступности с помощью psql в цикле. Результат фиксируем в отчёте.
while ! psql -h db-master.internal -U app myapp -c "SELECT 1" 2>/dev/null; do
echo "$(date): waiting..."
sleep 0.5
done
Типичное время failover с Patroni — 10–30 секунд. Свяжитесь с нами, чтобы обсудить архитектуру вашей базы данных. Наш опыт гарантирует стабильность.
Дополнительные сведения: Patroni и PostgreSQL synchronous replication.
Ссылки:
- Patroni — основное решение для PostgreSQL.
- PostgreSQL synchronous replication — официальная документация.







