ADG Оставить заявку
Блог Данные и аналитика 5 мин чтения

Patroni 3.0 и Citus: обновляем PostgreSQL HA-кластер клиента и чиним split-brain

Обновили Patroni с 2.1 до 3.0 на продуктивном кластере клиента. Новый алгоритм leader election решил проблему split-brain при нестабильном канале связи.

Контекст момента

Patroni 3.0 - встроенная поддержка Citus и новый алгоритм failover без потери транзакций при сетевом разделении

В октябре вышел Patroni 3.0 - мажорный релиз с двумя крупными изменениями: встроенной поддержкой Citus и переработанным алгоритмом failover. У нас как раз был подходящий повод обновиться: клиент с DWH-инфраструктурой несколько месяцев жаловался на периодические инциденты с лидером кластера. Не катастрофические - но достаточно неприятные, чтобы разобраться с ними до конца года.

Что было не так на Patroni 2.1

Кластер - три ноды PostgreSQL 14, Patroni 2.1, DCS через etcd. Всё по классике. Проблема проявлялась при кратковременных потерях сетевого пакета между нодами - примерно раз в неделю-две, чаще в ночные часы, когда канал между датацентрами загружен резервными копиями.

При потере связи продолжительностью 8-15 секунд Patroni 2.1 иногда принимал решение о смене лидера. Это само по себе нормально - в этом и смысл failover. Проблема была в том, что при восстановлении соединения старый лидер не всегда корректно уходил в статус реплики: возникала ситуация, когда оба узла короткое время считали себя первичными. Несколько транзакций за это время теряли консистентность.

По сути - классический split-brain при нестабильном сетевом канале. В Patroni 2.x это решалось настройкой ttl и loop_wait - чем больше значения, тем меньше ложных срабатываний, но тем медленнее реакция на реальный сбой. Мы крутили эти параметры несколько месяцев, нашли баланс который работает приемлемо, но не идеально.

Что изменилось в Patroni 3.0

Ключевое в релизе - введение понятия quorum-based leader election вместо простого TTL на ключ в DCS. В 2.x лидером считался узел, который удерживает ключ в etcd с нужным TTL. В 3.0 добавлена явная проверка кворума среди реплик перед сменой лидера: новый лидер не может взять роль primary без подтверждения от большинства нод, и при этом старый лидер явно уведомляется о том, что кворум принял решение против него.

На практике это означает, что при кратковременном сетевом разделении, когда ни одна из частей кластера не имеет кворума, Patroni 3.0 предпочитает ждать восстановления соединения, а не немедленно инициировать failover. Это именно то поведение, которое нам было нужно: канал гуляет 10-15 секунд, кластер держит позицию, соединение восстанавливается, все живут дальше без смены лидера.

Второе крупное изменение - встроенная поддержка Citus. До 3.0 использование Patroni с Citus требовало костылей: кастомного bootstrap-скрипта, ручного управления membership в coordinator, хитрых хуков. В 3.0 Citus-нода описывается в конфиге как citus с ролью coordinator или worker, Patroni управляет кластером целиком. У нас Citus не используется у этого клиента, но важно что поддержка появилась - есть другой проект где Citus стоит и вопрос об HA там открытый.

Обновление: что делали

Обновление с 2.1 до 3.0 потребовало небольшой работы по конфигу - часть параметров переименована или изменила семантику.

Первое - проверили версию etcd. Patroni 3.0 требует etcd 3.x; у клиента стоял etcd 3.4, всё нормально.

Второе - параметр ttl в 3.0 сохранился, но теперь взаимодействует с новым алгоритмом кворума. Оставлять значения из 2.x без пересмотра не стоит: мы снизили ttl с 30 до 20 секунд, потому что при наличии кворума кластер теперь значительно увереннее отличает реальный сбой от флапа канала.

Третье - в 3.0 появился параметр failsafe_mode. Это режим при котором Patroni не проводит автоматический failover при сетевом разделении, если primary недостижим из DCS, но реплики по-прежнему слышат primary напрямую. Включили в тестовом окружении, в продакшн не переносим - хочется понаблюдать за поведением базового кворума без дополнительных режимов.

Четвёртое - patronictl после обновления нужно проверить отдельно: команда patronictl topology в 3.0 выдаёт расширенный вывод с информацией о кворуме, и несколько скриптов мониторинга, которые парсили старый формат текстом, сломались. Пришлось перевести их на patronictl -f json.

Результат после двух недель

Кластер работает на Patroni 3.0 уже две недели. За это время сетевой канал флапал дважды - оба раза кластер промолчал, лидер не сменился, транзакции не потерялись. Раньше хотя бы один из этих эпизодов спровоцировал failover.

Это не означает что проблема решена навсегда - мы наблюдаем дальше. Но поведение кластера стало ощутимо ближе к тому, что мы ожидаем от HA-решения: не паниковать из-за кратковременных флапов, реагировать на реальные сбои.

Отдельный вопрос - мониторинг состояния кворума. В Patroni 3.0 через REST API /cluster теперь возвращается поле quorum с состоянием голосования. Добавили алерт в Zabbix: если кворум деградировал (меньше N-1 нод согласны с лидером) - предупреждение, даже если кластер формально работает. Это позволяет поймать ситуацию когда одна реплика отвалилась тихо, без смены лидера.

Citus-интеграция пока только изучаем в контексте другого проекта - там Patroni 2.x с ручными хуками, и переход на 3.0 выглядит разумным шагом именно ради встроенного управления координатором. Но это уже отдельная история.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.