27.1. Архитектура #

Благодаря встроенным возможностям отказоустойчивости Postgres Pro позволяет создать кластер с одним узлом-лидером и нескольмими узлами-последователями. Лидер является ведущим сервером BiHA-кластера, а последователи — репликами лидера.

Утилита bihactl позволяет инициализировать кластер и создавать узел-лидер, добавлять узлы-последователи, преобразовывать существующий узел в узел-лидер или узел-последователь в BiHA-кластере, а также проверять статус узлов кластера. Лидер доступен для чтения и записи, в то время как последователи доступны только для чтения и реплицируют данные с лидера в синхронном или асинхронном режиме.

Физическая потоковая репликация, реализованная в BiHA , обеспечивает отказоустойчивость, защищая от отказов серверов и системы хранения данных. При физической репликации файлы WAL узла-лидера синхронно или асинхронно отправляются на узел-последователь и применяются на нём. При синхронной репликации для каждой фиксации транзакции пользователь ожидает подтверждения от узла-последователя. Узел-последователь BiHA-кластера может использоваться для выполнения следующих задач:

  • Выполнение читающих транзакций в базе данных.

  • Подготовка отчётов.

  • Создание таблиц в оперативной памяти для пишущих транзакций.

  • Подготовка резервной копии узла-последователя.

  • Восстановление повреждённых блоков данных на узле-лидере путём получения этих блоков с узла-последователя.

  • Проверка повреждённых записей в файлах WAL.

Физическая потоковая репликация, реализованная в BiHA, обеспечивает защиту от следующих видов отказов:

  • Отказ узла-лидера. В этом случае статус узла-последователя повышается, и он становится новым лидером кластера. Повышение выполняется либо вручную с помощью функции biha.set_leader, либо автоматически с помощью выборов.

  • Отказ узла-последователя. Если последователь настроен как асинхронный, отказ никак не отразится на лидере. Если для последователя используется синхронная репликация, отказ приведёт к остановке транзакции на лидере, так как он перестанет получать подтверждение транзакций от последователя и транзакция не сможет завершиться. Подробное описание того, как настроить синхронную репликацию в BiHA-кластере, находится в Подразделе 27.3.7.

  • Сбой соединения между узлом-лидером и узлом-последователем. В этом случае лидер не может отправить, а последователь не может получить данные. Обратите внимание, что если пользователи подключены к лидеру, разрешать пишущие транзакции на последователе нельзя. Любые изменения, сделанные на последователях, нельзя будет восстановить на лидере. Чтобы избежать потери изменений, настраивайте сеть с резервными каналами. Лучше всего настроить свой канал передачи данных для каждого последователя, чтобы предупредить проблемы, связанные с единой точкой отказа.

В аварийной ситуации, например отказе операционной системы или оборудования, можно переустановить Postgres Pro и удалить расширение biha из shared_preload_libraries, чтобы вернуться к работе в максимально короткие сроки.

27.1.1. Варианты конфигурации кластера #

Существует несколько вариантов конфигурации кластера.

  • Три и более узлов, один из которых является лидером, а остальные — последователями.

    Ниже представлены возможные сценарии при отказе лидера или сбое сетевого подключения:

    • При отказе текущего лидера новый лидер избирается автоматически. Чтобы стать лидером, последователь должен получить максимальное количество голосов. Количество голосов должно быть больше или равно значению, заданному в параметре biha.nquorum.

    • При сбоях сетевого соединения внутри кластера BiHA кластер может разделиться на несколько групп узлов. В этом случае новый лидер избирается во всех группах, в которых количество узлов больше или равно значению biha.nquorum. После восстановления соединения лидер кластера выбирается между старым и новоизбранным лидером в зависимости от значения term. Узел с наибольшим значением term становится новым лидером. Рекомендуется установить значение biha.minnodes равным значению biha.nquorum.

  • Кластер из двух узлов, состоящий из лидера и последователя.

    Примечание

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

    Ниже представлены возможные сценарии при отказе лидера или сбоях сети:

    • При отказе лидера узел-последователь автоматически становится новым лидером, если для параметра конфигурации biha.nquorum установлено значение 1.

    • Если между лидером и последователем происходят сетевые сбои, и для обоих параметров конфигурации biha.nquorum и biha.minnodes установлено значение 1, кластер может разделиться на двух лидеров, доступных для чтения и записи. Подобных проблем позволяет избежать узел-рефери.

  • Конфигурация с одним узлом-лидером. Этот вариант возможно использовать, пока не будут настроены последователи. Логично, что узел нельзя заменить при сбое ввиду отсутствия последователей, которые могут стать лидером.

  • Кластер с тремя узлами, состоящий из лидера, последователя и рефери. Узел-рефери используется для голосования при выборе нового лидера, но сам не может стать лидером. При возникновении сбоев кластер с рефери ведёт себя как кластер с тремя узлами (лидером и двумя последователями). Чтобы подробнее узнать о рефери, обратитесь к Подразделу 27.1.3.

Примечание

  • Вы можете вручную назначить лидера с помощью функции biha.set_leader.

  • Рекомендуется установить для параметра biha.nquorum значение, большее или равное половине числа узлов в кластере.

  • При добавлении или удалении узлов из кластера всегда проверяйте значение biha.nquorum, учитывая наибольшее количество узлов, но не меньше, чем установлено в nquorum.

27.1.2. Выборы #

Выборы — это процесс определения лидера, который проводят последователи при отказе текущего лидера. В результате выборов лидером кластера становится последователь с наибольшим числом записей в WAL. Чтобы узел мог быть избран лидером, для параметров biha.can_be_leader и biha.can_vote этого узла должно быть установлено значение true.

Выборы проводятся с учётом кворума кластера, то есть минимального количества узлов, участвующих в голосовании. Значение кворума задаётся в параметре biha.nquorum при инициализации кластера командой bihactl init. Узлы, для которых в параметре biha.can_vote установлено значение false, исключаются из голосования и игнорируются в nquorum.

Чтобы начались выборы, последователи должны не получить максимальное количество сообщений о контроле состояния, заданное функцией biha.set_heartbeat_max_lost. На этом этапе один из последователей выдвигает себя в качестве кандидата в лидеры (CANDIDATE), и начинаются выборы. Если в этом случае лидер не получает заданное количество сообщений о контроле состояния от последователя, состояние последователя меняется на UNKNOWN для лидера. В синхронном кластере можно задать приоритет узлов с помощью параметра biha.node_priority. Если в кластере только два узла и вы хотите избежать возможных проблем разделения кластера во время выборов, создайте узел-рефери, который участвует в голосовании так же, как последователи. За подробностями обратитесь к Подразделу 27.1.3.

Например, в случае отказа одного узла-последователя в кластере из трёх узлов, где значение nquorum=2, узел-лидер продолжит работать. При отказе лидера в таком кластере два оставшихся последователя начнут выборы. После избрания нового лидера значение поколения кластера term увеличивается на единицу для всех узлов, то есть для нового лидера и оставшихся последователей term=2, а для старого лидера останется равным term=1. Когда старый лидер возвращается в кластер, происходит его понижение, то есть старый лидер становится последователем.

После избрания нового лидера последователи начинают получать файлы WAL уже от него. Обратите внимание, что при выборе нового лидера старый лидер понижается и становится недоступным для пишущих транзакций, чтобы избежать проблем разделения кластера (split brain). Вы можете вручную повысить старого лидера, используя функцию biha.set_leader. Механизмы кворума и поколения реализованы в BiHA на базе алгоритма консенсуса Raft.

27.1.3. Узел-рефери в BiHA-кластере #

В отказоустойчивом кластере можно создать узел-рефери, который участвует в выборах узла-лидера и помогает избежать потенциальной проблемы разделения кластера (split brain), состоящего только из лидера и последователя. В этом случае после создания рефери установите значение 2 для обоих параметров конфигурации biha.nquorum и biha.minnodes.

При создании рефери на него копируются только база данных biha_db и системные таблицы. База данных postgres и пользовательские данные не копируются.

Расширение biha поддерживает два режима работы рефери:

  • Режим referee. В этом режиме узел принимает участие только в выборах лидера, но не в репликации данных. Кроме того, для рефери не создаются слоты репликации ни на лидере, ни на последователях.

  • Режим referee_with_wal. В этом режиме узел участвует не только в выборах лидера таким же образом, как и в режиме referee, но и в репликации данных, и получает весь WAL с узла-лидера. Если на момент начала выборов больше всего записей WAL среди узлов кластера накопится на узле-рефери, то есть у рефери будет наибольший LSN, узел-последователь будет пытаться получить недостающие файлы WAL с рефери. Этот процесс важен для того, чтобы узел-рефери не перешел в состояние NODE_ERROR, что возможно при расхождении WAL. Для referee_with_wal, apply lag равен NULL и apply ptr невозможно изменить, так как рефери не применяет данные пользователя.

Вне зависимости от установленного режима работы узла-рефери, он отправляет и получает сообщения о контроле состояния по каналу управления, в том числе с использованием SSL, участвует в выборах так же, как и узлы-последователи, поддерживает функции мониторинга кластера и должен учитываться, когда задаётся значение параметра biha.minnodes. Обратите внимание, что рефери — это конечное состояние узла: его нельзя сделать лидером при помощи функции biha.set_leader, и он не может стать узлом-последователем. Если по какой-либо причине последователь «не видит» лидера, но его видит рефери, рефери не позволит последователю стать лидером. Если лидер с более высоким значением поколения term подключится к рефери, рефери понизит статус лидера с более низким значением term до последователя.