PostgreSQL
Streaming Replication: master и реплики
Декабрь 2020. AWS us-east-1 падает. У Slack - streaming replication на standby в другой AZ. Failover занял 4 минуты. Ни одного потерянного сообщения. У конкурентов без реплики - часы downtime. Streaming replication - это не enterprise-излишество, это страховка которая срабатывает именно тогда, когда нужна. PostgreSQL даёт всё из коробки: WAL streaming, hot standby для read scaling, synchronous mode для нулевого RPO.
- **GitLab.com** - streaming replication с hot standby: тяжёлые аналитические запросы (отчёты по активности) направляются на read replica, снимая 40% нагрузки с primary
- **Zalando** - patroni + streaming replication: автоматический failover менее чем за 30 секунд при падении primary, RDS Aurora заменяют self-managed Postgres для полного контроля
- **Supabase** - каждый проект получает primary + standby из коробки, pg_basebackup при создании проекта, synchronous replication для баз с финансовыми данными
Как работает потоковая репликация
**Streaming replication - передача WAL-потока от primary к standby в реальном времени.** Primary генерирует WAL при каждом изменении. WAL sender process на primary отправляет новые записи WAL receiver process на standby. Standby применяет полученные записи к своей копии данных. Отставание standby - обычно 1-100 мс.
**pg_stat_replication** - главный инструмент мониторинга репликации. Четыре LSN-позиции: sent (отправлено), write (записано в память standby), flush (сброшено на диск standby), replay (применено к данным). Разница replay_lsn и sent_lsn = реальное отставание.
Standby отстаёт на 500 МБ WAL. flush_lsn и replay_lsn почти равны. Что это означает?
pg_basebackup: начальная синхронизация
**pg_basebackup** создаёт точную физическую копию кластера PostgreSQL по сети. Единственный официальный способ инициализировать standby сервер. Копирует все файлы данных, создаёт checkpoint, включает в архив WAL-сегменты за время копирования - standby получает консистентную точку старта.
**pg_basebackup не блокирует primary.** Он использует механизм backup mode (pg_backup_start/pg_backup_stop). Primary продолжает обслуживать запросы. Все изменения за время копирования фиксируются в WAL и передаются через `--wal-method=stream`.
pg_basebackup с --wal-method=stream запущен на primary с 50 ГБ данных. Что происходит с production-трафиком во время копирования?
Настройка Standby и Recovery
**Standby режим активируется файлом `standby.signal`** в каталоге данных. PostgreSQL при наличии этого файла входит в режим continuous recovery - применяет WAL из primary. В PostgreSQL 12+ конфигурация вынесена в `postgresql.conf` и `postgresql.auto.conf`, файл `recovery.conf` больше не используется.
**primary_slot_name vs wal_keep_size:** без replication slot standby зависит от `wal_keep_size` на primary. Если standby отстаёт больше, чем хранится WAL - разрыв репликации. С replication slot - WAL сохраняется гарантированно, но риск заполнения диска при длительном отставании.
Standby настроен без replication slot, wal_keep_size = 1GB. Primary генерирует 500 МБ/час WAL. Standby упал на 3 часа. Что произойдёт при попытке переподключения?
Hot Standby: чтение с реплики
**Hot standby позволяет выполнять SELECT-запросы на standby сервере.** `hot_standby = on` (по умолчанию в современных версиях). Standby применяет WAL и одновременно обслуживает read-only запросы. Это позволяет разгрузить primary, направив аналитические и reporting-запросы на реплику.
**Routing запросов между primary и standby** - задача application layer или pgPool-II/HAProxy. Популярный паттерн: write-запросы на primary, read-запросы на standby. Gitlab направляет тяжёлые отчёты на dedicated read replica, снимая 40% нагрузки с primary.
Приложение выполнило INSERT на primary, затем немедленно SELECT на hot standby. SELECT может не найти только что вставленную строку. Почему?
Synchronous Replication: нулевой RPO
**Synchronous replication** - primary подтверждает транзакцию клиенту только после того, как standby записал WAL на диск. RPO = 0: даже при немедленном падении primary, standby имеет все данные. Цена: latency транзакций возрастает на время round-trip до standby (обычно 1-10 мс в LAN).
| synchronous_commit | Гарантия | Latency |
|---|---|---|
| off | Нет - возможна потеря последних транзакций | Минимальная |
| local (default) | WAL на диск primary | Нормальная |
| remote_write | WAL в память standby | +RTT/2 |
| on | WAL на диск standby | +RTT |
| remote_apply | Данные применены на standby | +RTT + apply time |
**Если synchronous standby недоступен - primary зависнет!** Все COMMIT будут ждать. Настройте `ANY 1 (standby1, standby2)` для отказоустойчивости, или мониторьте доступность standby и автоматически переключайтесь на асинхронный режим.
Streaming replication защищает от потери данных при любом падении primary
Асинхронная репликация допускает потерю последних нескольких транзакций (RPO > 0). Только synchronous_commit = 'on' даёт RPO = 0, но увеличивает latency
При async replication primary подтверждает COMMIT клиенту до отправки WAL на standby. Если primary падает между COMMIT и отправкой - эти транзакции потеряны. Среднее отставание 1-100 мс = потенциальная потеря данных за это время. Большинство production-систем принимают этот компромисс ради производительности
synchronous_standby_names = 'standby1'. Standby1 упал. Что происходит с INSERT на primary?
Итоги
- **WAL streaming**: primary отправляет WAL-поток через WAL sender, standby применяет через startup process. Отставание обычно 1-100 мс
- **pg_basebackup** создаёт начальную копию без блокировки primary - единственный официальный способ инициализировать standby
- **standby.signal** + primary_conninfo в postgresql.auto.conf запускают continuous recovery. recovery.conf устарел с PostgreSQL 12
- **Hot standby** (hot_standby=on) позволяет SELECT на standby - read scaling без дополнительных компонентов
- **Synchronous replication** (synchronous_standby_names) даёт RPO=0 за счёт +RTT latency. При падении sync standby primary зависает
Связанные темы
Streaming replication - основа для нескольких продвинутых возможностей PostgreSQL:
- WAL: Write-Ahead Log — Streaming replication передаёт WAL-поток - понимание WAL критично для диагностики репликации
- High Availability (HA) — Patroni/repmgr используют streaming replication как транспорт и автоматизируют failover при падении primary
- Logical Replication — Logical replication работает поверх WAL, но реплицирует только выбранные таблицы и поддерживает репликацию между разными версиями Postgres
Вопросы для размышления
- Primary генерирует 2 ГБ/час WAL, wal_keep_size = 1 ГБ. Standby используется для еженочных аналитических запросов, которые занимают 2 часа. Что произойдёт с репликацией? Какие два способа это исправить?
- Команда использует synchronous replication для финансовых транзакций. Standby в другом датацентре на 50 мс. Насколько synchronous replication замедлит каждую транзакцию? Стоит ли это того?
- После failover на standby старый primary поднялся. Как безопасно сделать его новым standby не потеряв данные?