Один сервер MariaDB переживает падение процесса, но не потерю машины. Galera собирает несколько узлов в кластер, где каждая запись подтверждается большинством, а данные автоматически догружаются на отставший узел. Это не «магия отказоустойчивости»: схема требует минимум трёх узлов, одинаковых настроек и понимания, что происходит при потере кворума. Разберём сборку и эксплуатацию.
Как работает Galera
Клиент пишет на любой узел. Транзакция формирует write-set, который рассылается всем участникам; они проверяют конфликты и подтверждают порядок. После сертификации запись применяется локально. Поэтому репликация называется виртуально синхронной: коммит подтверждается большинством, но применение на диске может отставать на доли секунды.
Отсюда два следствия. Чтение с любого узла может немного отставать, а конфликтующие записи в одну строку на разных узлах приводят к откату одной из транзакций. Приложение должно уметь повторить операцию.
Подготовка узлов
Нужны три машины с одинаковой версией MariaDB и Galera, синхронизированным временем и разрешением имён. В Debian пакет провайдера называется galera-4, утилита резервного копирования — mariadb-backup.
sudo apt install mariadb-server galera-4 mariadb-backup rsync socat pv
sudo systemctl stop mariadb
dpkg -L galera-4 | grep libgalera
getent hosts db1 db2 db3
Путь к библиотеке провайдера зависит от дистрибутива: на Debian это /usr/lib/x86_64-linux-gnu/galera/libgalera_smm.so, на RHEL — /usr/lib64/galera-4/libgalera_smm.so. Подставляйте фактический путь из вывода dpkg, иначе служба не стартует.
Конфигурация кластера
Настройки кладут в отдельный файл, который читается вместе с остальными. Ключевые требования — строковый формат бинлога, InnoDB по умолчанию и режим autoincrement, совместимый с параллельной записью.
[mysqld]
bind-address = 0.0.0.0
default_storage_engine = InnoDB
binlog_format = ROW
innodb_autoinc_lock_mode = 2
innodb_flush_log_at_trx_commit = 0
wsrep_on = ON
wsrep_provider = /usr/lib/x86_64-linux-gnu/galera/libgalera_smm.so
wsrep_cluster_name = "prod-cluster"
wsrep_cluster_address = "gcomm://10.0.0.11,10.0.0.12,10.0.0.13"
wsrep_node_name = "db1"
wsrep_node_address = "10.0.0.11"
wsrep_sst_method = mariabackup
wsrep_sst_auth = "sstuser:sst-secret"
wsrep_slave_threads = 4
wsrep_provider_options = "gcache.size=1G; gmcast.listen_addr=tcp://0.0.0.0:4567"
Параметр innodb_flush_log_at_trx_commit = 0 повышает скорость, но при аварийном выключении питания возможна потеря последних транзакций на одном узле. Если это неприемлемо, оставьте 1 и замерьте просадку. Значение wsrep_slave_threads подбирают по числу ядер, обычно от 4 до 8.
В wsrep_cluster_address не обязательно перечислять все машины: достаточно двух-трёх адресов, остальные участники находятся через обмен. Для четвёртого узла добавьте его адрес в список на каждой машине и перезапускайте службу по одной. Отдельный арбитр garbd помогает удержать кворум при двух рабочих узлах, но данные он не хранит.
Первый запуск
Первый узел поднимают в режиме начальной загрузки: он создаёт кластер с нуля. Остальные стартуют обычной службой и получают данные через SST.
sudo galera_new_cluster
sudo systemctl status mariadb
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
sudo systemctl start mariadb
Последняя команда выполняется на db2 и db3. Если первый узел не поднялся, смотрите journalctl -u mariadb: чаще всего мешает занятый порт 4567 или неверный путь к провайдеру.
SST и служебный пользователь
Для передачи снимка нужен пользователь с правами на чтение и блокировку. Его создают до добавления остальных узлов.
CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 'sst-secret';
GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT, BINLOG MONITOR
ON *.* TO 'sstuser'@'localhost';
FLUSH PRIVILEGES;
REPLICATION CLIENT и BINLOG MONITOR — исторические имена одной привилегии, в новых версиях используется второе. Метод mariabackup требует установленного пакета mariadb-backup, а также socat и pv; rsync-метод проще, но блокирует донора на всё время копирования.
Мониторинг состояния
Главный инструмент — переменные wsrep. Снимайте их раз в минуту и складывайте в систему мониторинга.
SHOW STATUS WHERE Variable_name IN (
'wsrep_cluster_size','wsrep_cluster_status','wsrep_ready',
'wsrep_connected','wsrep_local_state_comment',
'wsrep_flow_control_paused','wsrep_local_recv_queue_avg');
Нормальная картина: размер равен трём, статус Primary, ready и connected равны ON, состояние Synced. Рост flow_control_paused выше 0,05 означает, что применение не успевает за записью и кластер притормаживает отправителя. Очередь приёма больше единицы держится — повод добавить wsrep_slave_threads или ускорить диск. Полезно сравнивать wsrep_last_committed между узлами: расхождение в миллионы транзакций показывает, что один из них давно не применял записи.
Потеря узла и кворум
Кластер из трёх узлов переживает отказ одного. При потере двух кворума нет: узел переходит в состояние non-Primary и перестаёт принимать записи, хотя чтение может работать. Это защита от раздвоения данных.
SET GLOBAL wsrep_provider_options = 'pc.bootstrap=YES';
Эту команду выполняют только на самом продвинутом узле и только когда точно известно, что остальные не вернутся. Иначе получится два независимых кластера с разными данными, и свести их вручную будет крайне тяжело.
Обслуживание и DDL
Изменение схемы по умолчанию идёт в режиме Total Order Isolation: кластер ждёт выполнения ALTER на всех узлах. Для больших таблиц это часы блокировки. На время регламентных работ узел можно вывести из синхронизации, а для Rolling Schema Upgrade переключить метод.
SET GLOBAL wsrep_desync = ON;
SET GLOBAL wsrep_OSU_method = 'RSU';
ALTER TABLE orders ADD COLUMN note VARCHAR(255);
SET GLOBAL wsrep_OSU_method = 'TOI';
RSU применяет изменение только на текущем узле, поэтому схема временно расходится. Возвращать TOI нужно сразу после ALTER, а wsrep_desync выключать после резервного копирования — иначе узел безнадёжно отстанет.
Сеть и чек-лист
Откройте между узлами 3306 для клиентов, 4567 для обмена сообщениями, 4568 для инкрементальной передачи и 4444 для снимка.
sudo ufw allow from 10.0.0.0/24 to any port 3306 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 4567 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 4568 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 4444 proto tcp
Пользователь sstuser должен существовать на всех узлах, иначе передача снимка сорвётся при переключении донора.
- Одинаковая версия MariaDB и Galera на всех узлах.
- Три узла в разных зонах, синхронизация времени через chrony.
- gcache не меньше объёма writeset за час пик.
- Проверка восстановления из SST-копии раз в квартал.
- Алерты на non-Primary, рост очереди и flow control.
Итог
Galera даёт кластер с автоматическим включением узлов и защитой от раздвоения, но требует аккуратности: три узла, идентичные настройки, контроль кворума и понимание цены DDL. Начните с тестового стенда, прогоните отказ каждого узла по очереди и убедитесь, что приложение переживает кратковременный откат транзакций. Только после этого переносите продакшен и настраивайте алерты на состояние кластера.