BiHA (Built-in High Availability) — это расширение ПО СУБД Postgres Pro Enterprise, которое управляется утилитой bihactl и SQL-функциями. BiHA, вместе с улучшениями в ядре и управляющим процессом biha-worker, позволяет объединить несколько серверов в отказоустойчивый кластер. В этом High Availability кластере данные автоматически копируются между серверами с помощью физической репликации, и обеспечивается автоматическое переключение на резервный сервер в случае сбоя основного.

Что делает BiHA?
BiHA объединяет несколько серверов в HA кластер, автоматически настраивая репликацию между ними. Для этого используются специальная утилита bihactl, которую мы разработали для упрощения процесса конфигурирования HA кластера. Вам достаточно указать параметры узлов (например, их расположение и роли), и HA кластер будет собран автоматически.
Основное преимущество BiHA — возможность автоматического переключения роли мастера (лидера) на другой узел в случае сбоя. BiHA берёт на себя управление переключением, что значительно упрощает эксплуатацию.
Особенности BiHA
BiHA является частью ПО СУБД Postgres Pro Enterprise, что отличает её от сторонних решений. Это позволяет минимизировать сложности интеграции и повысить надёжность.
Простота установки и управления: BiHA значительно упрощает настройку и управление отказоустойчивого кластера, что делает её удобной для администраторов баз данных.
Параметр nquorum определяет минимальное количество узлов, необходимых для проведения выборов нового лидера. Если сеть разделяется, и лидер оказывается в изоляции, он автоматически переходит в режим Read-Only, запрещая любые изменения данных. Это гарантирует, что в другой части сети, где кворум соблюдается, будет выбран новый лидер, а данные на старом лидере останутся согласованными.

BiHA использует алгоритм RAFT для однозначного определения нового лидера. Этот алгоритм гарантирует, что в HA кластере всегда будет выбран только один лидер, что предотвращает разделение данных (Split-Brain).
Что же такое Raft?
Raft — это алгоритм распределённого консенсуса, предназначенный для упрощения и повышения надёжности управления распределёнными системами в сетях с ненадёжными узлами, где возможны сбои и асинхронная передача сообщений. Принцип Raft заключается в том, чтобы реплицировать лог транзакций на всех узлах через выбранного лидера, что обеспечивает согласованное состояние системы даже при отказах отдельных компонентов. Алгоритм разбит на понятные модули, такие как выбор лидера, репликация логов и обработка различных сбоев, что делает его более интуитивным для реализации и отладки по сравнению с более сложными алгоритмами консенсуса, например, Paxos. Такой подход позволяет системам работать корректно и сохранять целостность данных в условиях ненадёжных вычислений, что имеет решающее значение для современных распределённых IT-сред.
Узел рефери
Для принятия решений о выборе лидера всегда требуется минимум три участника. Если всего два узла в отказоустойчивом кластере, то разрыв сети между ними приведёт к ситуации, когда кворум не соблюдается, и оба узла не будут обслуживать запросы пользователей.
Когда же базы данных очень большие, то иметь лишнюю копию БД на третьем узле слишком дорого, поэтому для обеспечения надёжности в кластере BiHA может использоваться узел рефери. Это ещё один участник отказоустойчивого кластера, который располагается на отдельном сервере, с установленным ПО СУБД Postgres Pro Enterprise, работает экземпляр и управляющий процесс biha-worker, но на этом узле в БД нет пользовательских данных, поэтому нет таких же требований к дисковой подсистеме, что на других узлах. Этот узел выполняет важную роль в процессе голосования.
Обратите внимание: рефери не следует размещать на том же сервере или гипервизоре, что и мастер или реплика. Это исключает влияние на работу рефери тех же самых сбоев, что и на мастере.

Рефери используется в следующих случаях:
Для обеспечения кворума: в отказоустойчивых кластерах с небольшим количеством узлов (например, два узла) рефери помогает избежать ситуации, когда невозможно выбрать нового лидера из-за недостатка голосов для кворума.
Для накопления WAL: рефери может получать и накапливать журнал транзакций (WAL) с лидера. В случае сбоя, рефери может передать накопленные валы новому лидеру, что особенно полезно, если реплика не успевает получить или применить валы. Узел рефери может быть синхронным или асинхронным, в зависимости от конфигурации отказоустойчивого кластера.
Приоритеты узлов
Совсем недавно в BiHA появилась поддержка приоритетов узлов. Это решение было разработано в ответ на запросы заказчиков, которым нужно было контролировать, какой именно узел станет лидером в случае сбоя основного сервера.
Приоритеты работают только в синхронном HA кластере по очень простой причине: в асинхронном режиме мы не можем гарантировать, что какая-то конкретная из реплик имеет наиболее актуальные данные (WAL) на момент сбоя. Если бы выбор лидера происходил, когда все реплики в асинхронном режиме, то, несмотря на приоритеты, была бы выбрана именно реплика, которая содержит максимум данных, то есть, наименее остальных отстаёт от Лидера. В синхронном же режиме BiHA выбирает реплику в соответствии с указанными приоритетами, конечно же, при наличии актуального WAL.

Приоритеты позволяют задать задержку (в секундах), в течение которой реплика не будет выдвигать себя кандидатом на роль лидера. Например:
если у одного узла приоритет 10, а у другого 0 (самый высокий приоритет), то реплика с приоритетом 10 будет ждать 10 секунд, прежде чем выдвинуть себя кандидатом;
реплика с приоритетом 0 (высший приоритет) сразу выдвинет себя кандидатом и, скорее всего, станет новым лидером;
если реплика с высоким приоритетом по какой-то причине не сможет стать лидером, то через 10 секунд реплика с приоритетом 10 выдвинет себя кандидатом.
Такая система приоритетов обеспечивает мягкую балансировку и исключает полный отказ HA кластера, даже если некоторые узлы временно недоступны.
Реплики, которые никогда не станут лидерами
Некоторые заказчики сталкиваются с ситуацией, когда определённая реплика вообще не должна становиться лидером. Например:
Серверы с ограниченными ресурсами: это могут быть серверы, которые используются исключительно для сохранности данных, но не подходят для выполнения роли лидера из-за недостаточной производительности.
Реплики для чтения: на такие реплики может быть направлена нагрузка для выполнения запросов на чтение. Однако, если на такой реплике выполняется долгий запрос, она может отставать в применении WAL, и её выбор в качестве лидера приведёт к потере данных.
Для таких случаев в BiHA добавлен параметр can_be_leader=false (не может быть лидером). Если этот параметр включён, реплика никогда не станет лидером.
Параметр can_be_leader также помогает в создании геораспределённых HA кластеров, что особенно актуально для заказчиков, использующих несколько дата-центров (ЦОДов). Узел HA кластера с параметром can_be_leader=false можно разместить в резервном ЦОДе, создав таким образом реплику, которая не станет автоматически лидером в другом ЦОД, и администратору не придётся из-за этого переносить все сервера приложений в другой ЦОД. Это решает также одну из ключевых проблем при работе с несколькими ЦОДами: заказчики часто хотят, чтобы переключение между ЦОДами происходило только вручную, не все хотят доверять автоматике, особенно в случаях, когда переключение на резервный ЦОД требует не только смены лидера в базе данных, но и переноса других приложений.

Ручное переключение позволяет администратору активировать резервный ЦОД, убедившись, что все приложения и системы готовы к переходу. В случае выхода из строя всего основного дата-центра в резервном ЦОДе будет реплика с полной копией базы данных, которая постоянно получала изменения с основного ЦОДа, и поэтому содержит все данные. Чтобы перевести её в рабочий режим, достаточно лишь включить параметры can_be_leader=true и настроить параметр biha.minnodes=1, которые позволяют этому узлу после применения параметров временно работать без других узлов. Если же требуется при сбое всего основного ЦОДа развернуть целиком HA кластер BiHA в резервном ЦОД автоматизировано, то можно это сделать буквально одной командой.
Обработчики событий (Callbacks)
В BiHA была добавлена возможность создания пользовательской SQL-функции обработчиков событий BiHA. Эта функция позволяет выполнять пользовательский SQL-код при изменении состояния отказоустойчивого кластера, например, при выборе нового лидера или выходе узла из строя.
Обработчики могут быть использованы для:
оповещения администраторов — например, создания алертов в системах мониторинга;
интеграции с другими приложениями — например, уведомления прокси, балансировщиков, или даже серверов приложений о смене лидера, чтобы они могли перестроить свои пулы соединений;
изоляции старого лидера — в некоторых случаях требуется полная изоляция старого лидера буквально на физическом уровне (например, перезагрузка или отключение сети или электричества у сервера).

Обработчики могут выполнять разные задачи, но важно избегать ситуации, когда обработчик изменяет состояние кластера BiHA, иначе это вызовет бесконечный цикл изменений и, соответственно, бесконечный вызов функций обработчика.
В каких случаях пригодится BiHA
BiHA уже активно используется многими клиентами начиная с версии ПО СУБД Postgres Pro Enterprise 16. Наши пользователи отмечают, что эта технология обеспечивает надёжность и удобство в эксплуатации.
Мы рекомендуем использовать BiHA, если у вас появилась задача построения отказоустойчивых кластеров ПО СУБД Postgres Pro Enterprise. Новые функции, такие как узел рефери, приоритеты, параметр can_be_leader, поддержка геораспределённых HA кластеров и обработчики событий, делают её идеальным решением для обеспечения высокой доступности данных.
Подробнее о настройке и возможностях BiHA можно узнать в документации ПО СУБД Postgres Pro Enterprise (ссылка).