Перейти к основному содержимому

Режим отказоустойчивости 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