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.
Например, в случае отказа одного узла-последователя в кластере из трёх узлов, где значение
, узел-лидер продолжит работать. При отказе лидера в таком кластере два оставшихся последователя начнут выборы. После избрания нового лидера значение поколения кластера term увеличивается на единицу для всех узлов, то есть для нового лидера и оставшихся последователей nquorum
=2
, а для старого лидера останется равным 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
до последователя.