Максим Милютин m.milyutin@postgrespro · patroni: кворум из 2-ух узлов...

78
Максим Милютин [email protected] Stolon vs. Patroni HA решения для PostgreSQL

Upload: others

Post on 01-Jul-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Максим Милютин[email protected]

Stolon vs. PatroniHA решения для PostgreSQL

Page 2: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Для успеха технологии реальные факты должны быть важнее пиара, ибо природу обмануть невозможно

Ричард Фейнман(из доклада в комиссии Роджерса)

Page 3: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Матчасть

Page 4: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Физическая репликация

PostgresMaster

walsender

PostgresAsync replicawalreceiver

PostgresSync replicawalreceiver

WAL записи

Page 5: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Кластера на базе физической репликации

● Aрхитектура shared-nothing (без общего диска)

● Реплицируются физические изменения, описанные WAL

● Поддерживается режим чтения из реплики hot standby

● Готовые инструменты управления:○ создание реплики - pg_basebackup от мастера, восстановление из стороннего бэкапа

○ promote нового мастера

○ откат не реплицированных изменений на бывшем мастере - pg_rewind

○ мониторинг реплик - pg_stat_replication

Page 6: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Сложности кластера на базе встроенной логической репликации● Нет перепозиционирования реплик на новый мастер

○ прогресс репликации завязан на позицию в WAL мастера - LSN (log sequence number)○ нет аналога GTID как в MySQL

● Нет аналога pg_rewind (легковесная ресинхронизация бывшего мастера)

● Ограниченные возможности

○ не реплицируются DDL, последовательности (sequence)

● TODO в кластерных решениях Stolon/Patroni

○ для обновления мажорной версии PostgreSQL без простоя кластера (rolling upgrade)○ https://github.com/sorintlab/stolon/issues/519○ https://github.com/zalando/patroni/issues/538

Page 7: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Типы репликации

● Асинхронная

● Синхронная (мастер ожидает подтверждения коммита на репликах)○ remote_write - ожидание записи коммита в кэш ОС○ remote_flush (synchronous_commit = on) - ожидание сброса коммита на диск

(режим по умолчанию)○ remote_apply - ожидание “проигрывания” коммита на реплике (консистентное

чтение)

● “Степень синхронности” регулируется на уровне транзакций

https://www.postgresql.org/docs/current/warm-standby.html#SYNCHRONOUS-REPLICATION-PERFORMANCE

Page 8: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Полусинхронная репликация

● При синхронной репликации потеря реплики блокирует кластер на запись

● Подмножество (вариативное со временем) реплик являются синхронными

● Синхронные реплики задаются:

○ приоритетами узлов (priority based synchronous replication)synchronous_standby_names = ‘FIRST k (s1 s2 … sN)’

○ кворумом на коммит (quorum based synchronous replication)synchronous_standby_names = ‘ANY k (s1 s2 … sN)’

https://www.postgresql.org/docs/current/warm-standby.html#SYNCHRONOUS-REPLICATION-HA

Page 9: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Потеря коммитов при синхронной репликации

● Сброс на диск коммита на мастере происходит до подтверждения на синхронных репликах

● Рестарт мастера “восстанавливает” изменения транзакций, ожидавших подтверждения коммита на репликах

● Failover на синхронную реплику теряет не реплицированные зависшие транзакции

https://github.com/sorintlab/stolon/blob/master/doc/syncrepl.md#handling-postgresql-sync-repl-limits-under-such-circumstances

Page 10: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Итого

● Есть инструменты управления PostgreSQL узлами:○ создание и инициализация узлов БД (initdb, pg_basebackup, восстановление из

стороннего бэкапа)

○ promote нового мастера, pg_rewind (demote) старого мастера

● Нет “третьего” арбитра, который:

○ определял падение действующего мастера

○ выдерживал желаемую конфигурацию кластера:

■ promote/demote узлов БД

■ перевод реплики в синхронный/асинхронный режим

Page 11: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Архитектура кластеров класса Stolon/Patroni

Page 12: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер

PostgresMaster

PostgresReplica

потоковая репликация

Арбитр

Health checksControl

Health checksControl

Page 13: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер

PostgresMaster

PostgresMaster

Арбитр

Health checksControl

Health checksControl (promote)

Page 14: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер. Изоляция мастера

PostgresMaster

PostgresReplica

потоковая репликация

Арбитр

Health checksControl

Health checksControl

Page 15: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер. Изоляция мастера

PostgresMaster

PostgresMaster

Арбитр

Health checksControl

Health checksControl (promote)

Page 16: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер. Split brain

PostgresMaster

PostgresMaster

Арбитр

Health checksControl

Health checksControl (promote)

клиентские соединения

клиентские соединения

Клиенты на старом мастере && асинхронная репликация

Page 17: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер. Фенсинг изолированного мастера

Агенты:● управляют узлами PostgreSQL● отправляют статус арбитру● “фенсят” изолированный узел

Агент 1PostgresMaster

Агент 2PostgresMaster

Арбитр

HeartbeatsControl

HeartbeatsControl

клиентские соединения

клиентские соединения

Page 18: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Изоляция неактуального мастера (fencing)

“Ограждение” от изменений мастера, изолированного от основного кластера (избегание split brain):

○ выключение узла (экземпляра PostgreSQL) - STONITH○ разрыв всех текущих соединений и отказ от приёма новых○ перевод БД в режим read-only

Page 19: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Примитивный автофейловер. Доступность арбитра

Агент 1PostgresMaster

Агент 2Postgres

Sync replica

Арбитр

HeartbeatsControl

HeartbeatsControl

потоковая репликация

Арбитр - единая точка отказа

Page 20: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Схема HA кластера, осуществляющего автофейловер

Aгент 1PostgresMaster

Aгент 3Postgres

Async replica

Aгент 2Postgres

Sync replica

Потоковая репликация

АрбитрАрбитрконсенсус

Арбитр

Прокси

Прокси

Прокси

клиентские соединения

Page 21: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Схема HA кластера класса Patroni/Stolon

Aгент 1Postgresmaster

Aгент 3Postgres

Async replica

Aгент 2Postgres

Sync replica

Потоковая репликация

АрбитрDCS узел

DCS узел

DCS узел

Арбитрконсенсус

АрбитрПрокси

Прокси

Прокси

DCS - Distributed Configuration System (Распределённая система конфигурации)

клиентские соединения

DCS:● Consul - Raft● Etcd - Raft● Zookeeper - Zab

(адаптация Paxos)управление кластером

Page 22: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● keeper (postgres-агент)управляет экземпляром PostgreSQL по спецификации, “спущенной”от sentinel

● sentinel (арбитр кластера)обнаруживает и мониторит все остальные компоненты, вычисляетоптимальную конфигурацию “мастер-реплики”

● proxyточка доступа к мастер узлу от клиентов

● KV-store (consul, etcd, etc)шина данных/управления/событий

https://github.com/sorintlab/stolon#architecture

Aрхитектура Stolon

Page 23: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Patroni bot (postgres-агент)○ управляет экземпляром PostgreSQL○ связаны друг с другом по REST API

● Арбитр кластера○ DCS

■ имплементация распределённого CAS■ поддержка TTL для ключа мастер узла

○ Patroni агенты. По REST API:■ участвуют в выборе нового мастера■ подтверждают падение мастер узла

● Прокси (балансировщик)сторонний настраиваемый компонент

https://blog.timescale.com/high-availability-timescaledb-postgresql-patroni-a4572264a831/#getting-started-with-patroni

Архитектура Patroni

Page 24: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Автоматическая реакция на инциденты в кластере (переключение роли мастера при недоступности текущего)

● Автоматически настраиваемые узлы баз данных (агенты берут на себя всю рутину по настройке и управлению PostgreSQL)

● Тесная интеграция с облачными решениями (kubernetes)

● Продукт класса DBaaS (database as a service)

HA кластер на базе PostgreSQL класса Patroni/Stolon

Page 25: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Инсталляция кластера под управлением Stolon/Patroni

Page 26: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

https://github.com/sorintlab/stolon/issues/313 https://github.com/maksm90/stolon_vmcluster

consul

consul

consul

postgres postgres

Streaming replicationkeeper

stolon-proxy

stolon-proxy

sentinel

sentinelclient

client

clientGossip, Raft

node1

node2 node3

keeper

Классическая инсталляция Stolon на 3-х узлах

Page 27: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Облачная инсталляция Stolon

- consul (DCS) узел

stolon-keeper

client

client

client

Streaming replication

stolon-proxystolon-proxy

stolon-proxy

stolon-sentinelstolon-sentinel

stolon-sentinel

stolon-keeper

Page 28: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● минимум 3 серверных узла, остальные клиентские● серверный узел хранит состояние, является мини БД и требует

стабильное (по времени) по записи/чтению хранилище● RAFT как консенсус-протокол между сервер-узлами● протокол Gossip для membership list / failure detection / leader election● внешние запросы принимаются любым узлом по HTTP/DNS.● уровни консистентности чтения:

○ stale - перенаправление на сервер-узел○ default - перенаправление на лидер (+1 round-trip)○ consistent - лидер проверяет удержание кворума (+2 round-trip)

https://www.consul.io/docs/internals/architecture.html

Распределённая система конфигурации (DCS) на примере consul

Page 29: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● C использованием REST API патрони агентов○ /master - { 200: master, 503: replica }○ /replica - { 503: master, 200: replica }○ пример c HAProxy [1]

● Через callback вызовы○ on_start, on_stop, on_reload, on_restart, on_role_change

● Подписка к изменениям (периодическое обновление) DCS○ confd, consul-template, custom scripts○ пример с confd/pgbouncer [2]

● Множество хостов в строке подключения○ jdbc:postgresql://node1,node2,node3/postgres?targetServerType=master○ postgresql://host1:port2,host2:port2/?target_session_attrs=read-write

Прокси в Patroni (master discovery)

1. https://www.consul.io/docs/internals/architecture.html2. https://github.com/zalando/patroni/tree/master/extras/confd

Page 30: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Через DNS сервер consul (service discovery)○ требует проброс DNS в локальной окружение клиента [1] и настройки

кэширования [2]

○ критика Github в кластере под управлением orchestrator [3]

○ пример использования в проде [4]

● Единый IP-адрес для мастер узла○ HAProxy + keepalived○ vip-manager [5]

Прокси в Patroni (master discovery)

1. https://www.consul.io/docs/guides/forwarding.html2. https://learn.hashicorp.com/consul/day-2-operations/advanced-operations/dns-caching3. https://github.blog/2018-06-20-mysql-high-availability-at-github/#moving-away-from-vip-and-dns-based-discovery4. https://pgconf.ru/2019/242817 https://pgconf.ru/2019/2428215. https://github.com/cybertec-postgresql/vip-manager

Page 31: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Все компоненты (keeper, sentinel, proxy) могут запускаться независимо друг от друга

● Инициализация кластера и баз данных:

stolonctl init …● Изменение параметров кластера (в т.ч. postgresql.conf / pg_hba.conf):

stolonctl update …● Перезагрузка PostgreSQL:

○ вручную (рестарт агентов stolon-keeper)

○ автоматически (параметр automaticPgRestart)

● Добавление/удаление узлов кластера происходит автоматически при запуске/останове stolon-keeper

Workflow работы с кластером Stolon

Page 32: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Инициализация кластера и баз данных при запуске patroni агентов

○ конфигурация кластера (секция bootstrap) передаётся в конфиге агента (можно в единственном экземпляре)

● Изменение параметров кластера (в т.ч. postgresql.conf / pg_hba.conf):patronictl edit-config …

● Перезагрузка PostgreSQL:○ patronictl restart ...

○ patronictl restart --role … соблюдая очерёдность мастер/реплики [1]

○ patronictl restart --scheduled … по расписанию

● Добавление/удаление узлов кластера происходит автоматически при запуске/останове patroni

Workflow работы с кластером Patroni

1. https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-ADMIN

Page 33: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Возможности Stolon/Patroni

Page 34: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● initdb - “c нуля”

● PITR - из бэкапа

○ сторонняя бэкап-система кастомизируется

● Standby cluster○ “бесшовная” миграция с существующей инсталляции

● На базе существующей инсталляции [1]

○ не поддерживается stolon (свой формат PGDATA)

● Восстановление реплик кастомизируется

Инициализация кластера. Patroni

1. https://patroni.readthedocs.io/en/latest/existing_data.html

Page 35: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Возможность восстановиться из бэкапа на любую точку по:

● времени● id транзакции (xid)● lsn транзакционной записи в журнале● именной записи в журнале

bootstrap: method: probackup probackup: command: “pg_probackup restore -B /path/to/backup --instance <scope> -D <datadir> --time=’2019-04-27 00:00:00 MSK’ \

--recovery-target-action=promote --timeline=latest” keep_existing_recovery_conf: true # recovery_conf: # recovery_target_action: # recovery_target_timeline: # restore_command: # recovery_target_time:

Восстановление кластера из бэкапа

Page 36: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Снятие “снимка” с мастера (pg_basebackup) по умолчанию○ единственная стратегия в Stolon

● “Заливка” из бэкапа○ актуально для больших баз (Тб+)

● Кастомизируемая последовательность стратегий восстановленияpostgresql: create_replica_methods: - probackup - basebackup probackup: command: pg_probackup restore -B /path/to/backup -D <datadir> --instance <scope> keep_data: True no_params: True basebackup: max-rate: '100M' checkpoint: 'fast'

Восстановление реплик. Patroni

Page 37: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Aгент 1postgres replicakeeper master

Aгент 3Postgres

async replica

Aгент 2Postgres

sync replica

Потоковая репликация

Postgres узел

Потоковаярепликация

Stolon cluster

https://github.com/sorintlab/stolon/blob/master/doc/standbycluster.md

Инициализация кластера. Standby cluster

Page 38: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Применение:

● прозрачная миграция с существующей инсталляции (требуется всего лишь перезаливка данных)

● мульти ДЦ кластер (теоретически возможен)

● stolonctl promote … для приведения кластера из standby режима в нормальный

Инициализация кластера. Standby cluster

Page 39: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● по умолчанию асинхронная

● при синхронной можно формировать кворум на запись (полусинхронная репликация) параметрами [1]:

○ minSynchronousStandbys - кол-во синхронных реплик в кластере, ниже которого запись в БД блокируется

○ maxSynchronousStandbys - желаемое кол-во синхронных реплик○ Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2]

● асинхронная реплика не становится мастером:○ при синхронной репликации○ при асинхронной репликации, если отставание по транзакционным логам (WAL) от

мастера превышает некоторый порог (maxStandbyLag)

1. https://github.com/sorintlab/stolon/blob/master/doc/syncrepl.md2. https://patroni.readthedocs.io/en/latest/replication_modes.html#synchronous-mode-implem

entation

Варианты репликации. Stolon

Page 40: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 4Postgres

async replica

Stolon-keeper 2Postgres

sync replica

Stolon-keeper 3Postgres

sync replica

кворум

минимальныйкворум

minSynchronousStandbys = 1maxSynchronousStandbys = 2

Полусинхронная репликация. Stolon

Page 41: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

minSynchronousStandbys = 1maxSynchronousStandbys = 2

Stolon-keeper 1Postgresmaster

Stolon-keeper 4Postgres

sync replica

Stolon-keeper 2Postgres

sync replica

Stolon-keeper 3Postgres

sync replica

Полусинхронная репликация. Stolon

Downtime на запись при переключении от 20-40 сек.

по умолчанию

Page 42: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

minSynchronousStandbys = 1maxSynchronousStandbys = 2

Полусинхронная репликация. Stolon

Stolon-keeper 1Postgresmaster

Stolon-keeper 4Postgres

sync replica

Stolon-keeper 2Postgres

sync replica

Stolon-keeper 3Postgres

sync replica

insertupdatedelete

Page 43: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

minSynchronousStandbys = 1maxSynchronousStandbys = 2

Stolon-keeper 1Postgresmaster

Stolon-keeper 4Postgres

sync replica

Stolon-keeper 2Postgres

sync replica

Stolon-keeper 3Postgres

sync replica

insertupdatedelete

Полусинхронная репликация. Stolon

Page 44: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

minSynchronousStandbys >= 1

Stolon-keeper 1Postgresmaster

Stolon-keeper 2Postgres

sync replica

insertupdatedelete

Двухузловой кластер. Синхронная репликация. Stolon

Page 45: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● synchronous_mode_strict: off (по умолчанию)

● Failover на не синхронизированную реплику не происходит

● Недоступность на запись в кластере при потере синхронной реплики по

умолчанию, 20-30 сек.

○ При штатном выводе реплики из строя переключение в асинхронный режим практически

мгновенный

● Переключение “догоняющей” реплики в синхронный режим происходит

при полной синхронизации

“Нестрогий” синхронный режим. Patroni

Page 46: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Не используются встроенные кворумные методы (FIRST или ANY) репликации

○ список синхронных реплик не определён при падении мастера [1]

○ TODO: quorum commit (ANY) в Patroni [2]

● На каждый реплицирующий узел автоматически создаётся репликационный слот

○ в patroni определяется флагом use_slots● При смене мастер роли возможна потеря реплики (позиции слотов не

реплицируются)

○ подбор wal_keep_segment (stolon)

○ восстановление wal из архива (patroni)

1. https://github.com/sorintlab/stolon/blob/master/doc/faq.md#does-stolon-uses-postgres-sync-replication-quorum-methods-first-or-any

2. https://github.com/zalando/patroni/pull/672

Репликация. Stolon/Patroni

Page 47: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● “Ограждение” от изменений мастера, изолированного от основного кластера (избегание split brain):○ выключение узла (экземпляра PostgreSQL) - STONITH (patroni + watchdog [1])○ разрыв всех текущих соединений и отказ от приёма новых (stolon)○ перевод БД в режим read-only (patroni)

● Привязка к кворуму DCS● Stolon-proxy, будучи TCP-прокси на мастер узел, является “fencer” узлов

БД○ связка cond + HAProxy эмулирует stolon-proxy в Patroni

● Фенсинг изолированных stolon-proxy происходит по таймауту (15 сек.)

Изоляция неактуального мастера (fencing)

1. https://github.com/zalando/patroni/blob/master/docs/watchdog.rst

Page 48: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

DCS узел

DCS узел

DCS узел

консенсусProxy

Proxy

Proxyклиентские соединения

Изоляция неактуального мастера (fencing)

Page 49: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgresmaster

Stolon-keeper 2Postgres

Sync replica

DCS узел

DCS узел

DCS узел

консенсусProxy

Proxy

Proxyклиентские соединения

Изоляция неактуального мастера (fencing)

Page 50: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

Sentinel leader

DCS узел

DCS узел

DCS узел

Sentinelконсенсус

SentinelProxy

Proxy

Proxy

клиентские соединения

Изоляция неактуального мастера (fencing)

Page 51: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgresmaster

Stolon-keeper 2Postgres

Sync replica

Sentinel

DCS узел

DCS узел

DCS узел Sentinelконсенсус Sentinel

leaderProxy

Proxy

Proxy

клиентские соединения

клиентские соединения

Фейловер stolon-sentinel лидера за 20 секStolon-proxy фенсится за 15 секStolon-sentinel leader - по умолчанию, за 15 сек

Изоляция неактуального мастера (fencing)

Page 52: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

DCS узел

DCS узел

DCS узел

DCS кворум

Proxy

Proxy

Proxyклиентские соединения

Postgres кворум

Изоляция неактуального мастера (fencing)

Page 53: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

DCS узел

DCS узел

DCS узел

DCS кворум

Proxy

Proxy

Proxyклиентские соединения

Postgres кворум

Изоляция неактуального мастера (fencing)

Привязка к кворуму DCSsynchronousReplication: true

Page 54: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Изоляция неактуального мастера (fencing)

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Sync replica

Stolon-keeper 2Postgres

Async replica

DCS узел

DCS узел

DCS узел

кворум

Page 55: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Изоляция неактуального мастера (fencing)клиентские соединения

кворум

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgresmaster

Stolon-keeper 2Postgres

Sync replica

DCS узел

DCS узел

DCS узел

Page 56: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Автоматическое восстановление в кластер бывшего мастера○ “бесшовная” синхронизация (recovery_target_timeline=latest) (patroni)

○ откат не реплицированных изменений (pg_rewind)

○ перезаливка узла от нового мастера или из бэкапа (patroni)

● Время недоступности кластера =

длительность выявления сбоя мастера +

длительность переключения мастер роли +

длительность обнаружения нового мастера клиентами

Аварийное переключение master-роли (failover)

Page 57: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Stolon

1. Первичное обнаружение сбоя мастера арбитром(ƛ1 + ƛ2) * sleepInterval, где: (до 10 сек по умолчанию)

○ ƛi - случайная величина от 0 до 1○ sleepInterval - период срабатывания каждого компонента (keeper, sentinel, proxy) в цикле

(по умолчанию, 5 сек)

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

Sentinel

Proxy

Proxy

Proxy

клиентские соединения

SentinelSentinel leader

DCS узел

DCS узел

DCS узел

консенсус

1

Page 58: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Stolon

1. Первичное обнаружение сбоя мастера арбитром2. Таймаут подтверждения сбоя (параметр failInterval, по умолчанию, 20 сек)

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

Sentinel

Proxy

Proxy

Proxy

клиентские соединения

SentinelSentinel leader

DCS узел

DCS узел

DCS узел

консенсус

1

2

Page 59: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Stolon

1. Первичное обнаружение сбоя мастера арбитром2. Таймаут подтверждения сбоя3. Вычисление нового мастера и promote выбранной реплики

(ƛ1 + ƛ2) * sleepInterval (по умолчанию, до 10 сек)

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Sync replica

Stolon-keeper 2Postgresmaster

Sentinel

Proxy

Proxy

Proxy

клиентские соединения

SentinelSentinel leader

DCS узел

DCS узел

DCS узел

консенсус

1

2

3

Page 60: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Stolon

1. Первичное обнаружение сбоя мастера арбитром2. Таймаут подтверждения сбоя3. Время вычисления нового мастера и promote выбранной реплики4. Переподключение прокси на новый мастер

(ƛ1 + ƛ2) * sleepInterval (по умолчанию, до 10 сек)

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Sync replica

Stolon-keeper 2Postgresmaster

Sentinel

Proxy

Proxy

Proxy

клиентские соединения

SentinelSentinel leader

DCS узел

DCS узел

DCS узел

консенсус

1

2

3

4

4

Page 61: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Время недоступности кластера =(ƛ1 + ƛ2) * sleepInterval + failInterval +(ƛ3 + ƛ4) * sleepInterval +(ƛ5 + ƛ6) * sleepInterval

где:○ ƛi - случайная величина от 0 до 1○ sleepInterval - период срабатывания каждого компонента (keeper, sentinel, proxy) в цикле

(по умолчанию, 5 сек)○ failInterval - таймаут подтверждения сбоя (по умолчанию, 20 сек)

при допушении, что○ время записи/чтения из DCS пренебрежимо мало○ Raft лидер / Sentinel лидер работоспособны (+ 20 сек. при sentinel failover)

● С настройками по умолчанию, от 20 до 50 сек.

Failover. Stolon

Page 62: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Patroni

1. Выявление сбоя мастераttl - ƛ * loop_wait, где: (20-30 сек по умолчанию)

○ ƛ - случайная величина от 0 до 1○ ttl - TTL ключа лидера в DCS○ loop_wait - период срабатывания patroni агентов

Patronj 1Postgresmaster

Patroni 3Postgres

Async replica

Patroni 2Postgres

Async replica

клиентские соединения

DCS узел

DCS узел

DCS узел

консенсусkey /leader TTL expired

key /leader TTL expired

Page 63: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Patroni

1. Выявление сбоя мастера2. Проверка сбоя и определение кандидатов для нового лидера (2 сек.)

2 сек. - timeout на GET /patroni

Patronj 1Postgresmaster

Patroni 3Postgres

Async replica

Patroni 2Postgres

Async replica

клиентские соединения

DCS узел

DCS узел

DCS узел

консенсус

GET /patroni -> timeout

GET /patroni -> timeout

GET /patroni -> wal_position: ...

Page 64: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Patroni

1. Выявление сбоя мастера2. Проверка сбоя и определение кандидатов для нового лидера3. Выборы нового лидера (практически мгновенно)

Patronj 1Postgresmaster

Patroni 3Postgres

Async replica

Patroni 2Postgres

Async replica

клиентские соединения

DCS узел

DCS узел

DCS узел

консенсус

Create /leader (CAS)

success

Page 65: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Failover. Patroni

1. Выявление сбоя мастера2. Проверка сбоя и определение кандидатов для нового лидера3. Выборы нового лидера (практически мгновенно)4. Promote выбранного лидера и переподключение клиентов

promote мгновенный, время переподключения зависит от типа прокси

Patronj 1Postgresmaster

Patroni 3PostgresMaster

Patroni 2Postgres

Async replica

клиентские соединения

DCS узел

DCS узел

DCS узел

консенсус

Page 66: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Время недоступности кластера =ttl - ƛ * loop_wait +2 +client_reconnection_timeout

где:○ ƛ - случайная величина от 0 до 1○ ttl - TTL ключа лидера в DCS○ loop_wait - период срабатывания patroni агента в цикле (по умолчанию, 10 сек)○ client_reconnection_timeout - время переподключения клиентов к мастеру

при допушении, что○ время записи/чтения из DCS пренебрежимо мало

● С настройками по умолчанию, от 22 до 37 сек.○ время переподключения, положим, до 5 сек.

Failover. Patroni

Page 67: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Stolon

○ stolonctl failkeeper … универсальная команда временного “отказа” узла○ Нет таймаута на подтверждение сбоя○ Способ планово вывести узел из кластера○ Master switchover: stolonctl failkeeper master_node …○ Sync standby switchover: stolonctl failkeeper sync_standby_node …○ Узел-кандидат на мастер роль выбирается автоматически среди

наиболее “продвинутых” по реплицированным WAL

● Patroni

○ patronictl switchover --master=... --candidate=... направляемый switchover○ Switchover по расписанию

Плановое переключение мастер роли (switchover)

Page 68: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Агент 1Postgresmaster

Агент 3Postgres

Async replica

Агент 2Postgres

Sync replica

Потоковая репликация

DCS узел

DCS узел

DCS узел

консенсусХранилище бэкапов

и архивовWAL-архивы

cron-taskбэкапскрипт

cron-taskбэкапскрипт

cron-taskбэкапскрипт Бэкапы

Бэкап кластера

Page 69: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Полные и инкрементные бэкапы создаются кастомными скриптами по плану (cron)

● Роль узла в кластере можно узнать запросом к DCS

● Архивные транзакционные логи (WAL):

○ сегментами в 16 Мб с мастер узла (archive_command=on)

○ потоком по протоколу физической репликации (pg_receive_wal)

● Наличие “внешнего” слота репликации для pg_receive_wal (параметр additionalMasterReplicationSlots в stolon)

○ пересоздание слота автоматическое при смене мастер роли

Бэкап кластера

Page 70: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Агент 1Postgresmaster

Агент 3Postgres

Async replica

Агент 2Postgres

Sync replica

Потоковая репликация

DCS узел

DCS узел

DCS узел

консенсус

pg_probackup серверХранилище бэкапов и

архивовWAL-архивы

probackupклиент Бэкапы

probackupклиент

probackupклиент

pg_probackup с поддержкой удалённых бэкапов

Бэкап кластера с pg_probackup

Page 71: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon-keeper 1Postgresmaster

Stolon-keeper 3Postgres

Async replica

Stolon-keeper 2Postgres

Sync replica

Отстающая реплика

кластер Stolon ● additionalMasterReplicationSlots● recovery_min_apply_delay = '12h'

Поддержка “отстающих” реплик. Stolon

Page 72: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Patroni 1Postgresmaster

Patroni 3Postgres

Async replica

Patroni 2Postgres

Sync replica

Patroni 4Отстающая реплика

кластер Patroni

Поддержка “отстающих” реплик. Patroni

● Custom recovery.conf○ recovery_min_apply_delay = '12h'

● Tags○ nosync○ nofailover○ nobalance

Page 73: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● Определить момент повреждения данных (логи, расширение pgAudit, кастомные расширения)

● Отсоединить отстающую реплику от мастера и настроить восстановление до момента повреждения

● Получить из восстановленной реплики консистентные данные и “залить” их в мастер

● Заново настроить репликацию с отстающим проигрыванием изменений от мастер узла в кластере

https://www.percona.com/blog/2018/06/28/faster-point-in-time-recovery-pitr-postgresql-using-delayed-standby/

Легковесное восстановление из отстающих реплик

Page 74: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● stolonctl status … человекочитаемый формат

○ списки всех компонентов (keeper, sentinel, proxy)

○ состояния (health checks) агентов stolon-keeper и экземпляров PostreSQL

○ дерево репликации узлов БД

● stolonctl clusterdata … - json-представление состояния кластера в DSC (машиночитаемый формат)

○ позиции проигранных WAL => задержка репликации для всех узлов кластера (аналог pg_stat_replication с задержкой)

○ роли (sync/async) для реплик

Мониторинг кластера. Stolon

Page 75: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

● patronictl list … человекочитаемый формат

○ состояния узлов (действия, выполняемые в данный момент)

○ роли узлов БД (master/sync/async)

○ задержка репликации

● GET /patroni … - json-представление состояния узла

○ GET /master GET /replica - роли узлов

● KV хранилище DCS

Мониторинг кластера. Patroni

Page 76: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Резюмируя

Page 77: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Stolon vs. Patroni● Patroni богаче на фичи (enterprise уровень)

● Stolon проще и удобнее в настройке и в эксплуатации

● SQL интерфейс - единственное средство контроля БД (общий недостаток сторонних решений)

○ Нет возможности:■ следить за логами■ видеть внутреннее состояния PostgreSQL

○ Неявные таймауты, убивающие слабо контролируемые процессы (recovery)■ convergenceTimeout, initTimeout, syncTimeout в stolon

● В ожидании встроенного автофейловера

○ MongoDB [1], CocroachDB [2]

1. http://openlife.cc/system/files/4-modifications-for-Raft-consensus.pdf2. https://www.cockroachlabs.com/docs/stable/architecture/replication-layer.html

Page 78: Максим Милютин m.milyutin@postgrespro · Patroni: кворум из 2-ух узлов - одна синхронная реплика в synchronousStandbyNames [2] асинхронная

Спасибо за внимание!

Максим Милютин [email protected]