Введение
В рамках данной темы мы рассмотрим ключевые аспекты построения отказоустойчивых систем, включая классификацию кластеров СУБД, основные требования к ним, разновидности отказов и методы их предотвращения, такие как репликация, а также изучим принципы консенсуса и кворума на примере отказоустойчивого кластера СУБД Pangolin.
Классификация кластеров СУБД
В данном курсе под компьютерным кластером понимается набор компьютеров, соединенных вычислительной сетью, способных совместно и скоординированно работать на выполнением общих задач. К числу таких задач, например, можно отнести исключение одномоментного выхода из строя всех компьютеров в кластере. Или, в качестве другого примера, такой задачей может быть распределение вычислений по компьютерам в кластере с последующим предоставлением агрегированного результата клиенту.
Как минимум, вычислительные кластеры состоят из:
- Узлов (nodes) — компьютеров, выполняющих вычисления, обработку и/или координацию;
- Сетевых соединений, в зависимости от типа которых кластер локальный или же распределенный.
К числу иных компонент кластера (в зависимости от дизайна) относятся:
- распределенная память;
- общее системы хранения данных;
- системы аппаратного распараллеливания и/или ускорения;
- системы питания;
- кондиционирование;
- мониторинг;
- системы безопасности;
- многое другое.
Одна из наиболее распространенных ныне концепций построения кластеров называется Shared Nothing. В таких кластерах не используются общие ресурсы, такие как разделяемая память или общие подсистемы хранения информации. Концепция таких систем подразумевает использование обычных компьютеров (computer from shelf — «компьютер со склада»), соединенных с помощью обычного коммутационного оборудования L2 OSI, например, Ethernet коммутаторов, и обычных L3/L4 маршрутизаторов.
Несмотря на отсутствие в таких системах специализированных компонентов, за счет дешевизны и относительной простоты, такие кластеры получили наибольшее распространение в наше время.
Компьютерные кластеры подразделяются на два основных типа:
- высокопроизводительные кластеры (HP - High Performance);
- кластеры высокой доступности (HA - High Avaliability).
Высокопроизводительные кластеры ориентированы на достижение наилучших показателей по одному или нескольким направлениям:
- количество одновременно обслуживаемых запросов;
- количество транзакций в секунду;
- минимальное время ответа клиенту;
- максимальная пропускная способность по данным;
- и тому подобное.
Когда говорят о высокопроизводительных кластерах часто используется термин «масштабируемость». То есть, способность системы улучшать некоторое целевое свойство системы (например, количество читающих транзакций) вследствие добавления в кластер дополнительных узлов.
Требования к кластерам высокой доступности
Кластеры высокой доступности, хоть и похожи по принципам построения на высокопроизводительные, работают над выполнением совсем других задач.
Эти задачи в самом общем смысле связаны с повышением надежности системы и обычно формулируются следующим образом:
- снижение общего времени простоя системы;
- максимизация времени наработки на отказ;
- минимизация вероятности потери информации;
- минимизация времени, необходимого для восстановления системы;
- минимизация объема теряемой в случае аварии информации;
- и тому подобное.
Термины «отказоустойчивость» и «высокая доступность» не являются синонимами.
Любая система требует периодического обслуживания, поэтому говоря о времени простоя системы надо помнить о:
- простоях, вызванных отказами;
- простоях, связанных с обслуживанием системы.
В идеале, время простоя высокодоступной системы должно стремиться к нулю. Поэтому считается, что обслуживание системы следует проводить так, чтобы как минимум остановка одного узла на обслуживание не приводила к отказу всего кластера.
То же самое касается и отказов – отказ одного узла не должен приводить к отказу кластера. Проблема, однако, в сетевых соединениях. Их наличие значительно усложняет борьбу с отказами.
Важнейшие параметры оценки кластеров высокой доступности:
RTO(Recovery Time Objective) — время, затрачиваемое на восстановление системы;RPO(Recovery Point Objective) — период времени, связанный с отказом, в течении которого данные могут быть потеряны.
Разновидности отказов
Отказы кластерных систем подразделяются на два основных типа:
- Отказ узла.
- Разделение сети.
Отказ узла
В случае отказа узел прекращает выполнять свою функцию в составе кластера. Такой отказ узла называется отказом первого типа. Например, в кластере физической репликации, состоящем из двух узлов – один узел является мастером, а другой узел — репликой.
Мастер физической репликации имеет право выполнять пишущие транзакции, а реплика — нет. Если мастер выходит из строя, то без специальных мер пишущие запросы будут невозможны и клиентам будет отказано в обслуживании. Специальные меры подразумевают повышение роли узла кластера с реплики до мастера. Если такие меры принимаются при возникновении отказа достаточно оперативно, то клиенты не столкнутся с отказом в обслуживании.
Для обнаружения отказа узла применяются специальные сетевые пакеты, называемые heartbeat или, иначе, keep alive. Получив подобный сетевой пакет, узел кластера обязан своевременно ответить на него.
Если же обнаруживается пропуск ответных пакетов от некоторого узла кластера, то запускается счетчик, по истечении которого узел считается вышедшим из строя, если от него так и не поступили ответные пакеты.
Повышение роли узла кластера, до сбоя являвшего репликой, выполняется с помощью операции повышения (или продвижения - promote).
Разделение сети
Разделение сети создает отказ второго типа и происходит в случае специфического сбоя в работе сетевого оборудования, когда исходно связанные узлы кластера оказываются в разделенных частях ранее единой сети. Такая ситуация гораздо опаснее, чем простой отказ первого типа.
Проблема в том, что в разделенной на части сети могут появиться два (или больше) независимых друг от друга узла, выполняющих пишущие запросы.
Произойти это может следующим образом:
- Сетевое оборудование сбоит, разделяя сеть на два или более независимых сегментов.
- Старый мастер продолжает выполнять пишущие запросы клиентов.
- В части сети, где остались лишь реплики, выбирается новый мастер, так как из-за сетевого сбоя для этих реплик старый мастер недоступен.
- Часть сети с новым мастером начинает обслуживать клиентов, которые могут и не подозревать, что сеть разделилась.
- При наличии двух независимых мастеров выполнение ими пишущих запросов приведет к нарушению целостности данных, которую практически невозможно будет устранить.
Описанная ситуация называется split-brain и она должна быть исключена в корректно работающем кластере.
Отказоустойчивый кластер Pangolin
Комплект программного обеспечения, на котором строится отказоустойчивый кластер Pangolin, составлен из нескольких программных пакетов. Важнейшие из них с точки зрения построения отказоустойчивого кластера:
pangolin-manager— система управления кластером, основанная наpatroni;pangolin-dbms— СУБД, на основе PostgreSQL;pangolin-pooler— пулер клиентских сессий, реализующий точку входа в кластер.
Подробнее о pangolin-dbms и pangolin-pooler мы поговорим в следующих темах урока, а сейчас давайте разберемся что такое Pangolin Manager:
[student@srv1 ~]$ rpm -qa 'pangolin-[pdm][bao]*'
pangolin-dbms-6.7-6.7.0-redos8.0.x86_64
pangolin-dbms-6.7-client-6.7.0-redos8.0.x86_64
pangolin-manager-2.1.13-redos8.0.x86_64
pangolin-pooler-1.5.6-redos8.0.x86_64
Pangolin Manager управляет узлами кластера, он обязательно должен быть установлен в кластерной конфигурации.
Основной исполняемый файл Pangolin Manager:
[postgres@srv1 ~]$ /opt/pangolin-manager/bin/pangolin-manager --help
usage: pangolin-manager.bin [-h] [--version] [--validate-config | --generate-sample-config | --generate-config] [--dsn DSN] [configfile]
positional arguments:
configfile Patroni may also read the configuration from the PATRONI_CONFIGURATION environment variable
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--validate-config Run config validator and exit
--generate-sample-config Generate a sample Patroni yaml configuration file
--generate-config Generate a Patroni yaml configuration file for a running instance
--dsn DSN Optional DSN string of the instance to be used as a source for config generation. Superuser connection is required.
В результате автоматизированной установки ПО с помощью Ansible в systemd устанавливается unit-файл конфигурации сервиса Pangolin Manager:
[student@srv1 ~]$ sudo systemctl list-unit-files | grep pangolin-manager
pangolin-manager.service enabled disabled
Автоматический запуск сервиса Pangolin Manager обеспечивается именно этой службой:
[student@srv1 ~]$ sudo systemctl status pangolin-manager
● pangolin-manager.service - Runners to orchestrate a high-availability PostgreSQL
Loaded: loaded (/usr/lib/systemd/system/pangolin-manager.service; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/system/service.d
└─10-timeout-abort.conf
Active: active (running) since Wed 2025-11-26 19:02:14 MSK; 1h 52min ago
Process: 625 ExecStartPre=/bin/mkdir -p /var/run/postgresql (code=exited, status=0/SUCCESS)
Process: 629 ExecStartPre=/bin/chown -R postgres:postgres /var/run/postgresql (code=exited, status=0/SUCCESS)
Main PID: 633 (pangolin-manage)
Tasks: 21 (limit: 4667)
Memory: 241.9M
CPU: 16.522s
CGroup: /system.slice/pangolin-manager.service
├─633 /opt/pangolin-manager/bin/pangolin-manager-bin/pangolin-manager.bin /etc/pangolin-manager/postgres.yml
├─767 /usr/pangolin-6.7/bin/postgres -D /pgdata/06/data/ --config-file=/pgdata/06/data/postgresql.conf --listen_addresses=0.0.0.0 -->
├─770 "postgres: Pobeda: logger "
├─771 "postgres: Pobeda: checkpointer "
├─772 "postgres: Pobeda: background writer "
├─774 "postgres: Pobeda: idle sessions terminator "
├─775 "postgres: Pobeda: authproc "
├─776 "postgres: Pobeda: password policy cache "
├─779 "postgres: Pobeda: integrity check launcher "
├─780 "postgres: Pobeda: license checker "
├─783 "postgres: Pobeda: patroni postgres 127.0.0.1(60548) idle"
├─796 "postgres: Pobeda: walwriter "
├─797 "postgres: Pobeda: autovacuum launcher "
├─798 "postgres: Pobeda: pg_cron launcher "
├─799 "postgres: Pobeda: logical replication launcher "
└─841 "postgres: Pobeda: walsender patroni <IP-Address2>(53192) streaming 0/6000000"
В этом выводе команды, отображающем статус службы, обратите внимание на следующую строку:
/opt/pangolin-manager/bin/pangolin-manager-bin/pangolin-manager.bin /etc/pangolin-manager/postgres.yml
То есть, главный конфигурационный файл, настраивающий поведение кластера посредством Pangolin Manager — /etc/pangolin-manager/postgres.yml.
Консенсус и кворум
Узлы кластера, работая независимо друг от друга, должны, тем не менее, иметь общее представление о единой топологии кластера.
Если говорить лишь о физической репликации, то единое представление о топологии кластера, как минимум, следующее:
- количество узлов в кластере;
- какой узел является мастером, то есть, имеет право выполнять пишущие транзакции;
- на каких узлах можно выполнять читающие транзакции.
Для принятия единого решения узлами кластера о его топологии существуют специальные сетевые протоколы распределенного консенсуса. В частности, такие протоколы определяют последовательность действий по достижению консенсуса.
Для достижения консенсуса важно чтобы большинство узлов кластера могло сформировать кворум. Если работающих узлов в кластере осталось настолько мало, что они не могут сформировать кворум, они как минимум не должны допускать выполнения пишущих запросов. Иначе говоря, если оставшиеся узлы не могут сформировать кворум, в кластере физической репликации не может быть мастера и, собственно, репликации.
Для формирования кворума в кластере должно остаться более половины узлов, то есть, N/2 + 1 узел, где N - общее число узлов кластера. Если в кластере четное количество узлов, то можно столкнуться с ситуацией, когда в результате отказа сетевого оборудования, формируется два изолированных подмножества узлов кластера с одинаковым числом членов.
Избежать подобной ситуации можно с помощью искусственного ограничения числа участвующих в определении кворума узлов кластера нечетным числом. Те узлы кластера, которые участвуют в определении кворума, называются голосующими. Таким образом, если в кластере имеется четное количество узлов, в голосовании могут принимать не все из них, обеспечивая нечетное число голосующих узлов.
Другой способ обеспечения кворума в кластерах с четным числом рабочих узлов (например, один мастер и одна реплика) состоит в добавлении специального узла, который не обслуживает клиентов, а лишь принимает участие в голосовании. Такие узлы называются арбитрами.
На практике применяется несколько разных протоколов обеспечения консенсуса и кворума, например, Raft и семейство Paxos.
Raft реализует алгоритм распределенного консенсуса и представляет собой машину состояний, в которой узлы кластера обмениваются специальными записями. Узел кластера, получив очередную запись протокола Raft самостоятельно следует указаниям, связанным с достижением целевого состояния. Командует состояниями узел, называемый лидером.
Одна из задач протокола распределенного консенсуса — выбор лидера. В случае выхода из строя лидера инициируется голосование или, иначе, выборы. В результате голосования должен быть выбран новый лидер.
Итак, в Raft имеются следующие состояния узлов:
Leader(лидер) является первоисточником информации о топологии кластера, сохраняет информацию о событиях топологии в специальном журнале.Follower(последователь) — получатель указаний от лидера.Candidate(кандидат) — претендент стать лидером в текущем голосовании, если оно происходит.
Программы, реализующие кворумные протоколы, в частности Raft, называются DCS (Distributed Consistency Store) — системы распределенного консенсуса.
Одна из популярных реализаций DCS — система etcd, представляющую собой распределенное хранилище пар ключ-значение. Для работы etcd требует наличия минимум двух узлов, но как говорилось ранее, лучше иметь нечетное количество узлов.
Система etcd используется в качестве DCS в отказоустойчивом кластере Patroni, являющимся сейчас одним из наиболее популярных кластерных решений для СУБД PostgreSQL.
В случаях, когда применение etcd в составе кластера СУБД Pangolin не допускается по какой-либо причине, в дистрибутивном комплекте имеется ПО Pangolin DCS, также реализующий Raft.