Режим отказоустойчивости DCS
Эта страница переведена при помощи нейросети GigaChat.
Проблема
Patroni в значительной степени полагается на распределенное хранилище конфигурации (DCS) для решения задачи выборов лидера и обнаружения разделения сети. То есть узлу разрешается запускать PostgreSQL в качестве основного только в том случае, если он может обновить блокировку лидера в DCS. Если обновление блокировки лидера не происходит, PostgreSQL немедленно понижается в должности и запускается только для чтения. В зависимости от того, какой DCS используется, шансы столкнуться с «проблемой» различаются. Например, при использовании Etcd, который используется только для Patroni, шансы близки к нулю, в то время как при использовании K8s API (поддерживается Etcd) это может наблюдаться чаще.
Причины текущей реализации
Сбой при обновлении блокировки лидера может быть вызван двумя основными причинами:
- разделение сети;
- повреждение DCS.
В общем случае на одном узле невозможно различить эти две причины, поэтому Patroni предполагает наихудший вариант – разделение сети. В случае разделенной сети другие узлы кластера Patroni могут успешно захватить блокировку лидера и перевести Postgres в разряд основных. Чтобы избежать «split-brain», старый основной узел понижается до истечения срока действия блокировки лидера.
Режим отказоустойчивости DCS
В Patroni реализована новая специальная опция – режим защиты от сбоев. Он может быть включен только через глобальную динамическую конфигурацию, хранящуюся в ключе DCS. Если режим защиты от сбоев включен и обновление блокировки лидера в DCS не удалось по причинам, отличным от несоответствия версии/значения/индекса, PostgreSQL может продолжать работать в качестве основного, если он может получить доступ ко всем известным членам кластера через REST API Patroni.
Детали низкоуровневой реализации
- В Patroni введен новый, постоянный ключ в DCS, названный
/failsafe
. - Ключ
/failsafe
содержит все известные члены данного кластера Patroni в данный момент времени. - Текущий лидер поддерживает ключ
/failsafe
. - Член кластера допускается к участию в гонке лидеров и становится новым лидером только в том случае, если он присутствует в ключе
/failsafe
. - Если кластер состоит из одного узла, ключ
/failsafe
будет содержать только один элемент. - В случае «отключения» DCS существующий основной участник соединяется со всеми участниками, представленными в ключе
/failsafe
, черезPOST /failsafe
REST API и может продолжать работать в качестве основного, если все реплики подтвердят это. - Если один из членов не отвечает, первичный узел понижается в должности.
- Реплики используют входящие запросы
POST /failsafe
REST API как индикатор того, что основной еще жив. Эта информация кешируется в течениеttl
секунд.
Часто задаваемые вопросы
-
Почему текущему основному узлу необходимо видеть ВСЕХ остальных членов кластера? Можно ли полагаться здесь на кворум?
Проблема заключается в том, что представление о кворуме может отличаться с точки зрения DCS и Patroni. Хотя узлы DCS должны быть равномерно распределены по зонам доступности, для Patroni такого правила нет, и что более важно, нет механизма для введения и обеспечения соблюдения такого правила. Если большинство узлов Patroni оказывается в проигравшей части разделенной сети (включая основную), а меньшинство узлов находится в выигрышной части, основная должна быть понижена в должности. Только проверка ВСЕХ остальных участников позволяет обнаружить такую ситуацию.
-
Что делать, если узел удаляется при повреждении DCS?
Если DCS недоступен, проверка «доступны ли ВСЕ остальные члены кластера» выполняется каждый цикл цикла сердцебиения (каждые
loop_wait
секунды). Если под/узел завершен, проверка завершится неудачно и PostgreSQL будет понижен до режима только для чтения и не восстановит работу до тех пор, пока DCS не будет восстановлен. -
Что произойдет, если все участники кластера Patroni будут потеряны при отключении DCS?
Patroni может быть настроен на создание новой реплики из резервной копии даже тогда, когда у кластера нет лидера. Но если новый участник отсутствует в ключе
/failsafe
, он не сможет захватить блокировку лидера и повысить его. -
Что произойдет, если основная система потеряет доступ к DCS, а реплики – нет?
Основная система выполнит код отказа и свяжется со всеми известными репликами. Эти реплики будут использовать эту информацию в качестве индикатора того, что первичный сервер жив, и не начнут гонку за лидером, даже если блокировка лидера в DCS истекла.
-
Как включить режим отказоустойчивости?
Прежде чем включать
failsafe_mode
, убедитесь, что версия Patroni на всех участниках обновлена. После этого можно использовать либоPATCH /config
API REST, либо patronictl edit-config -s failsafe_mode=true