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







