Оригинал: CNPG Recipe 13 — Configuring PostgreSQL Synchronous Replication — 10 сентября 2024.
Настройка синхронной репликации в CloudNativePG 1.24: quorum-based и priority-based подходы, управление synchronous_commit и достижение RPO = 0.
CloudNativePG 1.24 вводит новую стanzу .spec.postgresql.synchronous для гибкого управления синхронной репликацией PostgreSQL. Этот подход заменит устаревшие minSyncReplicas / maxSyncReplicas начиная с CloudNativePG 1.25.
Ключевые улучшения
- Поддержка quorum-based и priority-based синхронной репликации.
- Расширенный контроль над параметром
synchronous_standby_names.
Внутренняя синхронная репликация (внутри кластера)
Для минимизации риска потери данных в HA-кластере CloudNativePG рекомендуется quorum-based синхронная репликация. Она обеспечивает баланс между безопасностью данных и производительностью.
Принцип: коммит транзакции считается успешным только после того, как WAL-записи реплицированы на заданное количество реплик. Порядок не важен — PostgreSQL подтверждает от самых быстрых.
CloudNativePG автоматически поддерживает synchronous_standby_names в актуальном состоянии на протяжении всего жизненного цикла кластера.
Пример — кластер из 3 инстансов с quorum-based репликацией (минимум 1 реплика подтверждает транзакцию):
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: angus
spec:
instances: 3
storage:
size: 1G
postgresql:
synchronous:
method: any
number: 1После деплоя CloudNativePG устанавливает synchronous_standby_names в:
ANY 1 ("angus-2", "angus-3")Коммит ожидает подтверждения от любой одной из перечисленных реплик.
Внешняя синхронная репликация (между кластерами)
В on-premise окружениях с двумя отдельными Kubernetes-кластерами может потребоваться синхронная репликация между ними.
Пример: replica cluster brian во втором Kubernetes-кластере реплицирует данные из primary-кластера angus. Цель — обеспечить, чтобы designated primary в brian участвовал в синхронной репликации.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: angus
spec:
instances: 3
postgresql:
synchronous:
method: first
number: 2
maxStandbyNamesFromCluster: 1
standbyNamesPre:
- brianРезультирующий synchronous_standby_names:
FIRST 2 ("brian", "angus-2")Ключевые параметры:
method: first— priority-based: реплики подтверждают в порядке приоритета.maxStandbyNamesFromCluster: 1— только 1 инстанс изangusвключается в список.standbyNamesPre: [brian]—brianимеет наивысший приоритет.
Кластер
angusне контролирует кластерbrian. Ваша ответственность — мониторинг и доступностьbrian, чтобы не блокировать запись на primary.
Настройка synchronous_commit
Параметр synchronous_commit управляет тем, когда primary считает транзакцию успешной. Работает совместно с synchronous_standby_names и может быть переопределён на уровне транзакции через SET.
В продакшне
fsyncдолжен быть всегдаon.
Асинхронная репликация
Когда synchronous_standby_names пуст:
| Значение | Поведение |
|---|---|
off | Успех возвращается сразу после записи в WAL, без гарантии записи на диск. Риск потери данных. |
on | Успех после записи WAL на диск primary (по умолчанию). Долговечность гарантирована только на primary. |
Синхронная репликация
Когда synchronous_standby_names не пуст, доступны дополнительные уровни (по возрастанию долговечности):
| Значение | Поведение |
|---|---|
off | Как в асинхронной репликации. |
local | Успех после записи WAL на диск primary. Подтверждение от реплик не требуется. |
remote_write | Успех после записи WAL в память нужного числа реплик (до flush на диск). Компромисс между производительностью и долговечностью. |
on | Успех после записи и flush WAL на диск primary и нужного числа реплик. Полная долговечность. |
remote_apply | Успех только после применения транзакции (видимости) на синхронных репликах. Максимальная консистентность — чтение с реплики гарантированно отражает коммит. Полезно при автоматическом failover. |
Значения remote_write, on и remote_apply существенно снижают риск потери данных при внезапном отказе primary, обеспечивая RPO = 0 в HA-кластере.
Примечание: В редких edge-case’ах реплика может отправить подтверждение primary, но если primary упадёт до того, как передаст подтверждение приложению — приложение может воспринять транзакцию как незавершённую. Несмотря на это, синхронная репликация остаётся лучшим инструментом для достижения высокой долговечности данных.
Заключение
Стanza .spec.postgresql.synchronous в CloudNativePG предоставляет мощную абстракцию над synchronous_standby_names:
- Quorum-based (
method: any) — для кластеров внутри одного Kubernetes, где все инстансы равноправны. - Priority-based (
method: first) — для сценариев с внешними кластерами, где нужен приоритет реплик. synchronous_commit— тонкая настройка баланса между производительностью и долговечностью, вплоть до уровня отдельной транзакции.
В будущем CloudNativePG планирует поддержку приоритизации узлов, что откроет новые возможности — например, консистентные чтения через сервисы, привязанные к приоритетным репликам.