Введение
Для управления облачным кластером на базе PostgreSQL в нашем облаке используется Patroni. Именно он выполняет автоматическое переключение мастер-ВМ в случае проблем. Из-за высоких гарантий консистентности переключение мастера (то есть превращение одной из реплик в головной узел) — довольно деструктивное действие.
Подразумевается, что при переключении происходят следующие шаги:
- Выбранная реплика (желательно с синхронной репликацией) получает команду на отцепление от мастера (перестает получать от него WAL).
- На том хвосте WAL, что у нее есть, делает redo (применение выполненных транзакций, откат невыполненных), инкрементирует Timeline, переходит в обычный режим работы (то есть принимает запросы и на чтение, и на запись).
- Бывший мастер должен быть уничтожен (STONITH), так как у него нет инструмента понимания, что он не легитимный мастер, и чтобы он не продолжал обслуживать клиентов, проще всего его погасить.
Все это и делает служба Patroni (а для консенсуса между нодами она использует внешний DCS — etcd). При этом бывший мастер (если сам сервер в целом в порядке) сразу же переводится в статус реплики (используя утилиту pg_rewind). Таким образом кластер в целом продолжает работать. Было упомянуто, что переключение является деструктивным, что это значит?
- Транзакции, которые прошли commit и на актуальном мастере, и на потенциальном мастере — вне зоны риска. Поэтому следует выбирать синхронную реплику, так как они в теории имеют полностью идентичную информацию.
- Для транзакций, что не прошли commit полностью, начинаются приключения. Если текущий мастер успеет ответить клиенту об успехе транзакции, но это не дойдет до будущего мастера, клиент будет думать, что все было успешно, но эти данные потеряются. Если мастер не успеет ответить, то клиент получит команду на стоп (got immediate shutdown request), либо разрыв TCP (в зависимости от способа гибели мастера) и должен считать транзакцию зафейленной. Важнейшний паттерн написания приложений — зафейленные транзакции должны ретраиться самим приложением. То есть потеря данных в такой ситуации — вина приложения. Следующее подключение к кластеру должно проходить к новому мастеру.
Переключения
Как проводилось переключение:
- Все подключения производились через LB, который создается вместе с кластером.
- Во время переключения подавалась нагрузка через pgbench, чтобы кластер не простаивал.
- Использовался специальный скрипт, который инсертил каждую секунду.
Следует учитывать, что переключение может быть дольше, если на кластер идет много запросов и WAL для redo может оказаться много.
Штатное переключение
Также есть возможность ручного переключения мастера. Такие переключения самые быстрые, так как patroni не ожидает таймаута (вдруг это лишь флап на мастере).
Тип диска | Время переключения |
---|---|
dp1-ssd
|
не более 15 секунд
|
dp1-highiops
|
не более 8 секунд
|
Внештатное переключение
В качестве способа вывода мастера из строя — выключение сетевого интерфейса на мастере. Это довольно жесткая схема, так как из кластера пропадает и patroni демон, и etcd. Почему здесь дольше? Потому что у Patroni есть настройка ttl (по умолчанию 30 секунд). Столько он будет ждать, чтобы убедиться, что это не просто флап мастера. А потом уже начнется реальное переключение.
Тип диска | Время переключения |
---|---|
dp1-ssd
|
не более 45 секунд
|
dp1-highiops
|
не более 40 секунд
|