У вас 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 — офіційна документація.







