В Postgres Pro Standard и Enterprise отказоустойчивость уже встроена: BiHA — это часть самой СУБД. Не «реплика плюс набор внешних компонентов», как в опенсорсной PostgreSQL, а кластер Postgres Pro с физической репликацией, автоматическим и ручным переключением узлов, механизмом выборов и восстановлением узлов после сбоя.

Что такое BiHA и когда применяется

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

В основе BiHA — архитектура с узлом-лидером (Leader), доступным для чтения и записи, и узлами-последователями (Followers), открытыми только на чтение. Последователи получают от лидера WAL через физическую потоковую репликацию. В случае отказа лидера последователи автоматически определяют нового лидера с помощью механизма выборов.

BiHA незаменима в чувствительных к простоям системах, например:

  • платежи, заказы, биллинг, склад, логистика;

  • 1С, ERP, CRM и другие корпоративные системы;

  • внутренние платформы с большим числом пользователей;

  • базы, где реплицируются тяжёлые отчёты.

Главный смысл BiHA в том, что вокруг репликации появляется встроенный контур управления отказоустойчивостью.

Как работает BiHA

При настройке BiHA добавляет расширение biha в  shared_preload_libraries, создаёт служебную базу biha_db, роли для управления кластером и репликацией и вспомогательные конфигурационные файлы. Слоты репликации создаются и обслуживаются автоматически.

Основная утилита администрирования — bihactl. Она инициализирует кластер, отображает статус и конфигурацию, добавляет узлы и помогает сопровождать обновления. BiHA-кластер можно развернуть с нуля, а также создать из существующего экземпляра Postgres Pro или кластера с потоковой репликацией.

После включения BiHA управляет частью параметров репликации самостоятельно. Это необходимо, например, для автоматической перестройки топологии кластера при смене лидера.

Отказоустойчивость строится за счёт нескольких механизмов:

  • Автоматические выборы (Raft). При выходе лидера из строя последователи инициируют выборы по алгоритму консенсуса Raft. Новым лидером становится узел с наибольшим количеством голосов и самыми актуальными данными в WAL. Для успешных выборов требуется кворум (biha.nquorum).

  • Синхронная и асинхронная репликация. Кластер работает в асинхронном режиме по умолчанию или в режиме кворумной синхронной репликации — когда лидер ждёт подтверждения записи от заданного числа узлов, гарантируя нулевую потерю данных при аварии.

  • Узел-рефери (Referee). Специальный тип узла для защиты от split-brain: участвует в голосовании, но сам никогда не становится лидером. Работает в двух режимах: referee (только голосование) и referee_with_wal (голосование и хранение WAL).

  • Автоматическое самовосстановление. Если старый лидер возвращается после сбоя, система автоматически переводит его в статус последователя. BiHA самостоятельно выравнивает конфликтные записи WAL (алгоритм WAL trimming) или синхронизирует узел через pg_rewind без ручного вмешательства администратора.

Почему BiHA может быть лучше Patroni

Patroni — популярное опенсорсное HA-решение, которым пользуются многие команды. Оно отличается от BiHA моделью эксплуатации: Patroni требует отдельной установки и настройки, а в ядро СУБД Postgres Pro Enterprise и Standard уже встроены механизмы управления кластером, мониторинга и переключения. 

  • С Patroni команда собирает и сопровождает внешний HA-стек: DCS, настройки Patroni, правила failover, различные интеграции и процедуры восстановления. За такую гибкость приходится платить высокой ответственностью.

  • В Postgres Pro встроена большая часть HA-логики. Для enterprise-команды это часто важнее, чем свобода выбора внешних компонентов.

Преимущества BiHA по сравнению с самосборным HA-стеком:

  • меньше внешних компонентов между приложением и базой;

  • меньше интеграционных точек отказа;

  • единая документация на кластер, роли, параметры и процедуры;

  • встроенный рефери для защиты компактных схем от split-brain;

  • автоматическое понижение бывшего лидера после выборов;

  • автоматическая синхронизация узла через pg_rewind или WAL trimming;

  • штатный ручной switchover через biha.set_leader;

  • сервисный режим для плановых работ;

  • поддержка вендора.

Patroni может быть предпочтительнее, если команда отлично владеет опенсорсным стеком и предпочитает гибкость архитектуры.

BiHA подойдёт, когда бизнесу нужна поддерживаемая HA-платформа, а не набор компонентов, за совместимость и регламенты которого полностью отвечает внутренняя команда.

Proxima и KVik — надстройки над кластером

Proxima — это расширение, которое объединяет прокси-сервер, балансировщик нагрузки, пул соединений и кеш данных (KVik). В связке с BiHA оно может получать параметры кластера: число узлов, их адреса и порты, роли лидера и последователей. Когда лидер меняется, Proxima получает уведомление через колбэки и перенаправляет трафик на нового лидера.

Поскольку Proxima встроена в ядро СУБД, инфраструктуру не нужно дополнять отдельными внешними утилитами — меньше компонентов, меньше потенциальных точек отказа.

У Proxima два направления трафика:

  • P2L, Proxy-to-Leader — направляет клиентские подключения на лидер BiHA-кластера. Через этот порт идут записи и обычная нагрузка на чтение-запись.

  • P2F, Proxy-to-Follower, распределяет нагрузку на чтение по репликам. Это удобно для отчётов, тяжёлых SELECT-запросов и сервисов, которым не нужна запись.

Еще одна роль Proxima — выдача сессий из пула свободных соединений. PostgreSQL, в которой нет Proxima, создаёт отдельный бэкенд-процесс на подключение, а когда таких соединений тысячи, база начинает тратить ресурсы на обслуживание сессий. Пул соединений снижает накладные расходы и помогает сгладить пики.

Это особенно полезно в системах, где нельзя быстро переписать приложение под сложную логику подключения, — можно вынести маршрутизацию на уровень платформы.

KVik — это модуль для кеширования данных в оперативной памяти, использующий движок Proxima. Он работает как хранилище «ключ-значение» и поддерживает RESP (Redis Serialization Protocol) и базовые команды GET (прочитать по ключу), SET(создать или изменить) и DEL(удалить).

Часть данных — справочники, настройки, сессионные данные, курсы валют, статусы, небольшие профили — нужна приложению очень часто, но меняется редко. Обычно для такого слоя ставят отдельный Redis-кластер, а затем пишут код синхронизации между Redis и PostgreSQL.

KVik предлагает встроенный вариант: кеш находится внутри Proxima-процессов, а данные связаны с реляционными таблицами. При изменении данных через SQL соответствующая запись в кеше аннулируется, чтобы приложение не читало устаревшее значение.

Эта функциональность экспериментальная и имеет ограничения: кеш не реплицируется между узлами, TTL для ключей пока не поддерживается, есть ограничения по инвалидации и поддерживаются не все объекты. Поэтому KVik стоит рассматривать как перспективную надстройку для отдельных сценариев, а не как обязательную часть HA-кластера.

BiHA обеспечивает отказоустойчивость базы, Proxima помогает с подключениями и балансировкой, а KVik может стать дополнительным способом ускорить доступ к часто читаемым данным.

Сценарии использования BiHA

Классическая HA внутри одного ЦОД

В основе механизма — процедура голосования по алгоритму Raft: при потере лидера последователи выдвигают кандидатов, а решение принимается по кворуму голосов. Среди кандидатов система выбирает узел с наивысшим приоритетом и наиболее актуальным LSN в WAL — приоритет узла определяет задержку перед тем, как узел выдвигает себя кандидатом, а более высокое значение LSN означает более свежие данные.

Для защиты от split-brain применяется узел-рефери с двумя режимами: «обычный рефери», который только участвует в голосовании и передаёт статусы соседних узлов, и «рефери с WAL», который дополнительно хранит WAL-записи и может быть источником репликации для других узлов. Узел переходит в терминальное состояние Node Error по нескольким причинам: закончился WAL, инвалидация слота репликации, проблема синхронизации WAL, ошибка при выполнении rewind или разошедшаяся история WAL.

Каскадная репликация

«Каскад» нужен не только между ЦОД, но и внутри одного ЦОД, если много последователей. Для выбора источника репликации узлам не подходит статичный список — при добавлении/удалении узла или перестроении топологии после сбоя списки сложно поддерживать, могут возникать циклы, а тестировать динамическое поведение списков сложно. Поэтому BiHA использует приоритеты подключения по типу узла — например, правило «подключаться только к Leader» или «сначала к Leader, потом к Follower» — а если при перестроении топологии всё же образуются циклы, BiHA умеет их обнаруживать и разрывать, что упрощает принятие решения о новой топологии кластера.

Многоуровневая геораспределённость (GDBiHA)

Для катастрофоустойчивости при отказе целого ЦОД есть несколько шагов эволюции архитектуры:

  • резервный узел в другом ЦОД — узлу можно запретить становиться лидером (can_be_leader=false) и голосовать (can_vote=false), а кворум для дата-центров рассчитывается отдельно, чтобы избежать некорректных переключений, при аварии основного ЦОД кластер поднимается на резервном узле вручную, переключая флаги can_be_leader/can_vote обратно в true;

  • резервный кластер в другом ЦОД — аналогичная логика применяется не к одному узлу, а к целому набору узлов резервного ЦОД;

  • сценарий с тремя ЦОД — при аварии в одном ЦОД кластер переключается на другой ЦОД, а выборы ведущего дата-центра организованы по тому же принципу, что и выборы лидера внутри одного ЦОД.

Из практики построения катастрофоустойчивости выявились требования, которые лежат в основе идеи вложенной BiHA: индивидуальные тайм-ауты внутри ЦОД и между ЦОД, поддержка каскадной репликации, поддержка «своего» лидера в резервных ЦОД и поддержка определения ведущего ЦОД. Решение — иерархия из трёх уровней: узел (физический сервер) → сегмент (объединение узлов) → кластер (объединение сегментов). Для сегментов вводится понятие Front Follower, между сегментами используется один канал каскадной репликации, для каждого сегмента можно задавать персональные настройки, а в резервном сегменте проводятся отдельные выборы главного ведомого узла. При этом смена ведущего сегмента — то есть переключение ЦОД-лидера на резервный ЦОД — выполняется вручную администратором через функцию biha.set_leader; в отличие от выборов лидера внутри сегмента, которые проходят автоматически по алгоритму Raft, автоматическое переключение на уровне сегментов документацией не поддерживается.

Плановое обслуживание оборудования

Помимо ручного переключения лидера, существует сервисный режим как способ выключить или изолировать узел на время обслуживания: узлу запрещается переходить в статус Candidate, то есть он временно исключается из процедуры выборов лидера.

Определение сбоев и фенсинг

Отдельный механизм, дополняющий сценарии отказоустойчивости, — обнаружение сбоев через отсутствие Heartbeat между лидером и последователями (параметры hb_period и hb_max_lost) и последующий фенсинг «потерянного» узла. Предлагается три механизма фенсинга: переключение состояния Postgres из RUN в HOT_STANDBY, запрет транзакций на уровне backend через check_hook, и watchdog самого biha-worker, который отслеживает собственную работоспособность по времени.

Бесшовный мажорный апгрейд 

Команды bihactl для автоматизации процедуры миграции позволяют создать лидера с новой версией Postgres Pro и переместить последователей в обновлённый кластер практически без простоя. Минимальная пауза в работе потребуется для перенастройки клиентских подключений на работу с новым кластером.

Масштабирование читающей нагрузки 

Узлы-последователи открыты для чтения — на них можно направлять тяжёлые SELECT-запросы, отчёты или задачи резервного копирования без нагрузки на лидера.

Ограничения

  1. BiHA не отменяет проектирование инфраструктуры. Кворум нужно рассчитывать осознанно. Для двух узлов без рефери есть риск split-brain. Синхронную репликацию нужно соотносить с задержками сети и требованиями RPO/RTO. Параметры хранения WAL нужно выбирать под реальную нагрузку, иначе отстающий узел может перейти в NODE_ERROR или WAL заполнит диск.

  2. BiHA не заменяет резервное копирование. Логическая ошибка, массовое удаление или поврежденные данные могут реплицироваться на последователей. Для таких случаев нужны резервные копии, проверка восстановления и PITR.

  3. BiHA не превращает PostgreSQL в систему записи в нескольких регионах. Последователи доступны только на чтение. Если приложению нужна одновременная запись на нескольких площадках, нужен другой архитектурный подход.

Главное

BiHA делает отказоустойчивость частью самой платформы СУБД Postgres Pro. Это важно для систем, где простой напрямую влияет на деньги, операции и доступность сервисов: кластер сам выбирает нового лидера, перестраивает репликацию и возвращает восстановившиеся узлы в рабочую топологию.

Главное преимущество такого подхода — предсказуемость эксплуатации. Команде не нужно собирать HA-контур из разрозненных компонентов, отдельно проектировать DCS, правила failover и процедуры возврата узлов после аварии. BiHA закрывает базовый слой отказоустойчивости, Proxima добавляет маршрутизацию подключений и балансировку чтения, а KVik может ускорить отдельные сценарии с часто читаемыми данными.

При этом BiHA не отменяет архитектурную дисциплину: кворум, режим репликации, задержки сети, резервное копирование и процедуры восстановления всё равно нужно проектировать под конкретные RPO, RTO и профиль нагрузки. Но если цель — получить поддерживаемую enterprise-платформу с встроенным HA-контуром, BiHA становится одним из ключевых аргументов в пользу выбора Postgres Pro Enterprise или Standard.