Синхронная мульти-master репликация в MySQL появилась сравнительно недавно, однако была востребована довольно давно. До этого момента пользователям приходилось использовать либо репликацию в режиме Master-Slave и переключать операции записи на ведомый сервер при отказе главного сервера, либо использовать довольно сложный вариант с Master-Master репликацией на основании двунаправленной Master-Slave репликации.
Стоит отметить, что в конфигурации Master-мульти-Slave реализация автоматического переключения становится сложнее и не всегда возможна без человеческого вмешательства. Более того, репликация Master-Slave является не полностью синхронной, отчего могут быть проблемы с потерей данных при выходе сервера Master из строя, если ведомый сервер существенно отстал.
С появлением Galera все стало намного проще. Для надежной работы вам необходимо эксплуатировать нечетное количество серверов, например 3 или 5 для защиты от партиционирования, так, чтобы при ситуации, когда кластер «рассыпался» Galera могла принять обоснованное решение о том, является ли наблюдаемый сегмент кластера целостным.
В самом простом случае вес каждого узла является равным 1, соответственно, если для наблюдаемой части кластера сумма весов узлов > N/2, эта часть кластера считается работоспособной. Например, для 3х узлов:
Ситуация 1: отказ узла MySQL Решение: два оставшихся узла могут работать, т.к. 2 > 3/2 Ситуация 2: отказ сети узла MySQL Решение 1: два оставшихся узла могут работать, т.к. 2 > 3/2 Решение 2: узел с отказавшей сетью не может работать, т.к. 1 < 3/2 Ситуаций 3: отказ центрального коммутатора Решение: кластер неработоспособен, т.к. для каждого узла 1 < 3/2
В общем случае, для безотказной работы кластера Galera вам необходимо обеспечить надежность:
- избыточность сетевой инфраструктуры (стеки, MLAG, OSPF);
- качественное энергоснабжение и разделение на независимые домены отказа, например, 3 VM в одном сервере не могут считаться надежным решением для формирования кластера Galera.
В более сложных топологиях, узлы кластера могут иметь различные веса. Общая формула кворума выглядит следующим образом:
При использовании Galera стоит помнить, что чем больше в кластере узлов, тем шире будут нужны каналы обмена данными, поскольку репликация осуществляется дублированием отправки пакетов от каждого узла каждому. Если у вас много узлов и интенсивный обмен трафиком между ними, рекомендуется переключиться на репликацию по multicast, если ваша сеть это поддерживает.
Конечно, помимо достоинств у кластера Galera есть и ограничения (перевод фрагмента с официального сайта MariaDB):
- Репликация поддерживается только для таблиц в формате InnoDB;
- Не поддерживается репликация явных блокировок, включая
LOCK TABLES
,FLUSH TABLES {явный список таблиц} WITH READ LOCK
, (GET_LOCK ()
,RELEASE_LOCK ()
,…); Правильное использование транзакций позволяет преодолеть эти ограничения, однако, если движок использует вышеприведенные операции, они должны выполняться но одном и том же узле. Операции глобальной блокировки, такие какFLUSH TABLES WITH READ LOCK
поддерживаются. - Все таблицы должны иметь первичный ключ (поддерживаются первичные ключи на нескольких столбцах). Операции
DELETE
не поддерживаются в таблицах без первичного ключа. Кроме того, строки в таблицах без первичного ключа могут извлекаться на разных узлах в разном порядке. - Общий журнал запросов и журнал медленных запросов не могут быть перенаправлены в таблицу. Если вы включите эти журналы, то вы должны отправлять вывод записей журналов в файл, установив
log_output = FILE
. - Транзакции XA не поддерживаются.
- Хотя Galera явно не ограничивает размер транзакции, набор записей обрабатывается как один резидентный буфер памяти, и в результате очень большие транзакции (например,
LOAD DATA
) могут отрицательно повлиять на производительность узла. Чтобы избежать этого, системные переменные wsrep_max_ws_rows и wsrep_max_ws_size ограничивают размер строки в транзакции 128 КБ, а максимальный размер транзакции составляет 1 ГБ. При необходимости пользователи могут увеличить эти ограничения. В будущих версиях будет добавлена поддержка фрагментации транзакций.
Мы рассмотрим самую простую настройку кластера Galera с тремя узлами, как изображено на следующей картинке:
Для дальнейшей работы рассмотрим как установить MariaDB для различных операционных систем. В этом руководстве мы будем использовать текущую стабильную версию MariaDB версии 10.3.
Установка MariaDB
Установка в Debian 9
Произведем базовую установку MariaDB 10.3, рекомендованную поставщиком для Debian 9 Stretch:
sudo apt-get install -y software-properties-common dirmngr sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8 sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.3/debian stretch main' sudo apt update sudo apt install -y mariadb-server
Проверьте корректность установки, соединившись с MariaDB с помощью клиента командной строки:
mysql -uroot -e 'SELECT version();' +---------------------------------------------+ | version() | +---------------------------------------------+ | 10.3.13-MariaDB-1:10.3.13+maria~stretch-log | +---------------------------------------------+
Соединение работает, если вы получили вывод похожий на приведенный выше. Теперь, когда установка MariaDB завершена, можно перейти к настройке кластера.
Установка в Ubuntu 18.04
Произведем базовую установку MariaDB 10.3, рекомендованную поставщиком для Ubuntu Linux 18.04:
sudo apt-get install software-properties-common sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu bionic main' sudo apt update sudo apt install -y mariadb-server
Проверьте корректность установки, соединившись с MariaDB с помощью клиента командной строки:
mysql -uroot -e 'SELECT version();' +--------------------------------------------+ | version() | +--------------------------------------------+ | 10.3.13-MariaDB-1:10.3.13+maria~bionic-log | +--------------------------------------------+
Соединение работает, если вы получили вывод похожий на приведенный выше. Теперь, когда установка MariaDB завершена, можно перейти к настройке кластера.
Установка в Ubuntu 16.04
Произведем базовую установку MariaDB 10.3, рекомендованную поставщиком для Ubuntu Linux 16.04:
sudo apt-get install software-properties-common sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 sudo add-apt-repository 'deb [arch=amd64,arm64,i386,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu xenial main' sudo apt update sudo apt install -y mariadb-server
Проверьте корректность установки, соединившись с MariaDB с помощью клиента командной строки:
mysql -uroot -e 'SELECT version();' +--------------------------------------------+ | version() | +--------------------------------------------+ | 10.3.13-MariaDB-1:10.3.13+maria~xenial-log | +--------------------------------------------+
Соединение работает, если вы получили вывод похожий на приведенный выше. Теперь, когда установка MariaDB завершена, можно перейти к настройке кластера.
Установка в CentOS 7
Произведем базовую установку MariaDB 10.3, рекомендованную поставщиком для CentOS 7. Сначала необходимо добавить репозиторий пакетов MariaDB 10.3 в Yum:
sudo nano /etc/yum.repos.d/mariadb.repo
со следующим содержимым:
# MariaDB 10.3 CentOS repository list - created 2019-03-28 19:13 UTC # http://downloads.mariadb.org/mariadb/repositories/ [mariadb] name = MariaDB baseurl = http://yum.mariadb.org/10.3/centos7-amd64 gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck=1
Теперь можно выполнить установку пакетов:
sudo yum install -y MariaDB-server MariaDB-client && sudo systemctl enable mariadb && sudo systemctl start mariadb
Проверьте корректность установки, соединившись с MariaDB с помощью клиента командной строки:
mysql -uroot -e 'SELECT version();' +-----------------+ | version() | +-----------------+ | 10.3.13-MariaDB | +-----------------+
Соединение работает, если вы получили вывод похожий на приведенный выше. Теперь, когда установка MariaDB завершена, можно перейти к настройке кластера.
Подготовка к настройке кластера
Настройка кластера Galera довольно проста, однако требует выполнения ряда подготовительных действий.
Конфигурация сетевых параметров
Для корректной работы кластера необходим доступ к следующим портам:
- 3306 (TCP). Стандартный порт MariaDB — для клиентских подключений MySQL и передачи снимков состояния, использующих метод
mysqldump
. Этот порт можно изменить, указав другое значение. - 4567 (TCP/UDP). Порт репликации Galera — для трафика репликации кластера Galera. Репликация в режиме
multicast
использует оба протокола на этом порту. Порт можно изменить, установивwsrep_node_address
. - 4568. Порт IST — для инкрементной передачи состояния. Можно изменить, установив
ist.recv_addr
вwsrep_provider_options
. - 4444. Порт SST — для всех методов передачи состояния снимком, кроме
mysqldump
. Может быть изменено путем установкиwsrep_sst_receive_address
.
Мы считаем, что узлы соединены приватной доверенной сетью, не требующей брэндмауэра. Если у вас используется брэндмауэр, вам необходимо открыть вышеуказанные порты для обеспечения пропуска трафика. Если вы планируете использовать multicast
, порт 4567 должен быть открыт как для пропуска трафика UDP, так и для TCP.
Примечание для пользователей Cloud2 NetPoint: В облаке Cloud 2 NetPoint для каждого аккаунта или проекта помимо публичной сети предоставляется еще и приватная сеть, в которую входят только виртуальные машины этого аккаунта. Эта сеть безопасна, работает на скорости 10 Gbit/s, и именно она должна использоваться для настройки кластерных решений вместо публичной сети.
Шифрование трафика кластера
Если ваши узлы кластера Galera будут работать в различных сегментах сети или просто в небезопасной среде, вам необходимо обеспечить шифрование передаваемых между ними данных. Шифрование может быть обеспечено с помощью использования встроенной поддержки SSL. В этой статье такая настройка не рассматривается.
Дополнительные параметры конфигурации MySQL
Для корректной настройки кластера необходимо определить ряд переменных MySQL. Сначала рассмотрим каждую из них, а потом приведем их все вместе в конфигурационном файле.
default-storage-engine = innodb
— кластер Galera работает только с использованием InnoDB, вы должны использовать этот тип таблиц для реализации кластера;log-bin = /var/log/mysql/mysql-bin
— задает имя для журнала операций;log-bin-index = /var/log/mysql/mysql-bin.index
— задает имя индекса журнала операций;binlog-format = 'ROW'
— формат журнала должен быть построчным, это требование для Galera;innodb_autoinc_lock_mode = 2
— режим блокирования, который наилучшим образом подходит для реализации конкурентных генераторов, но может привести к генерации идентификаторов с пропусками;innodb_rollback_on_timeout = 1
— при таймауте транзакции будет осуществлен ее откат;innodb_lock_wait_timeout = 600
— максимальное время ожидания блокировки строк транзакцией;innodb_doublewrite = 1
— двойная запись InnoDB: в буфер двойной записи и в файлы данных;innodb_flush_log_at_trx_commit = 0
— оптимизация, которую не стоит использовать вне кластера; позволяет вызывать синхронизацию не после каждой транзакции, а один раз в секунду;bind-address = 0.0.0.0
— адрес, который слушает MySQL, для разрешения и IP4 и IP6 используйте::
;wsrep_provider = /usr/lib/galera/libgalera_smm.so
— путь к библиотеке Galera;wsrep_cluster_address = "gcomm://10.0.0.1,10.0.0.2,10.0.0.3"
— адреса узлов кластера, так же может быть адрес мультикаст, если используется репликация по мультикаст;wsrep_on = ON
— включает режим репликации;wsrep_cluster_name = "cluster"
— задает имя кластера;wsrep_sst_method = rsync
— механизм синхронизации состояния узлов после старта (поддерживается rsync, mysqldump, xtrabackup); rsync считается универсальным и подходящим для большинства случаев;wsrep_node_address = "10.0.0.1"
— адрес узла, который будет использоваться для репликации;wsrep_node_name = "node1"
— имя узла в кластере.
Параметр wsrep_sst_method
Отдельно хотелось бы остановиться на данном параметре. Он определяет способ первоначального переноса состояния между новым узлом и существующим узлом кластера. Существует три варианта, которые отличаются по способу работы:
- Mysqldump — состояние с удаленного узла переносится на локальный с помощью mysqldump, при этом используется порт 3306 для соединения с удаленным узлом, на время переноса состояния узел донор блокируется. Этот способ считается самым медленным.
- Rsync — на узле доноре и инициаторе запускается rsync, с помощью которого состояние переносится на инициатор, на время переноса узел донор блокируется. Этот способ является быстрым и оптимален для больших СУБД.
- Rsync_wan — используется rsync, но для переноса используется алгоритм переноса изменений, что позволяет минимизировать трафик;
- Xtrabackup — используется утилита Percona Xtrabackup. Способ является быстрым и неблокирующим, однако для его использования требуются дополнительные настройки и установка утилиты xtrabackup.
Мы будем использовать способ rsync, который является рекомендуемым способом по умолчанию.
Общий вид конфигурационного файла galera.cnf
[mysqld] max_connections=350 log-bin=/var/log/mysql/mysql-bin log-bin-index=/var/log/mysql/mysql-bin.index binlog-format = 'ROW' default-storage-engine=innodb innodb_autoinc_lock_mode=2 innodb_rollback_on_timeout=1 innodb_lock_wait_timeout=600 # # не меняйте значение этой переменной при использовании Galera innodb_doublewrite=1 # # для ускорения операций # позволяет не ждать синхронизации с FS # для большей безопасности можно установить в "1" innodb_flush_log_at_trx_commit=0 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_provider=/usr/lib/galera/libgalera_smm.so wsrep_cluster_address="gcomm://10.0.0.1,10.0.0.2,10.0.0.3" wsrep_on=ON # Galera Cluster Configuration wsrep_cluster_name="cluster" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address="10.0.0.1" wsrep_node_name="node1"
Для каждого узла кластера в конфигурационном файле будут меняться только значения параметров wsrep_node_address
, wsrep_node_name
. Остальные параметры должны быть одними на всех трех узлах.
Настройка с использованием multicast
При использовании многоадресной доставки в файл настроек необходимо внести некоторые изменения:
wsrep_provider_options = "gmcast.mcast_addr=224.33.0.6" wsrep_cluster_address="gcomm://224.33.0.6"
Здесь адрес 224.33.6.1
— доступная вам многоадресная группа, в которой вы будете передавать сообщения кластера.
Другие параметры wsrep_*
Перечисленных выше параметров вполне достаточно для настройки. Если вы хотите узнать о других параметрах, то полный перечень тех, которые относятся к настройкам кластера Galera, находится в официальной документации.
На каждом узле остановите MariaDB, в каталоге /etc/mysql/conf.d
создайте файл galera.cnf
с указанными выше настройками для Galera:
sudo nano /etc/mysql/conf.d/galera.cnf sudo systemctl stop mariadb
Не забудьте установить корректные значения параметров wsrep_cluster_address
, wsrep_provider_options
(multicast группа или другие опции, если используются), wsrep_node_address
, wsrep_node_name
, wsrep_cluster_name
.
Инициализация кластера
Запуск первого узла Galera. Выберите любой из узлов и инициализируйте кластер. Операция не деструктивная, никакие данные не удаляются и не повреждаются:
sudo galera_new_cluster
Запуск оставшихся узлов. Каждый из оставшихся узлов запускается как обычно:
sudo systemctl start mariadb
Проверьте состояние кластера с помощью значения переменных wsrep_*:
$ mysql -uroot -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster%';" +--------------------------+--------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------+ | wsrep_cluster_conf_id | 5 | | wsrep_cluster_size | 3 | | wsrep_cluster_state_uuid | 15a6ec3c-648e-11e9-ae72-0715b07d89d9 | | wsrep_cluster_status | Primary | | wsrep_cluster_weight | 3 | +--------------------------+--------------------------------------+ $ mysql -uroot -e "SHOW GLOBAL STATUS LIKE 'wsrep_incoming%'\G" *************************** 1. row *************************** Variable_name: wsrep_incoming_addresses Value: 10.120.28.219:3306,10.120.29.124:3306,10.120.28.207:3306
Если теперь на одном из узлов выполнить команду sudo systemctl stop mariadb
, то вы немедленно увидите как изменится вывод вышеприведенных команд:
$ mysql -uroot -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster%';" +--------------------------+--------------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------------+ | wsrep_cluster_conf_id | 6 | | wsrep_cluster_size | 2 | | wsrep_cluster_state_uuid | 15a6ec3c-648e-11e9-ae72-0715b07d89d9 | | wsrep_cluster_status | Primary | | wsrep_cluster_weight | 2 | +--------------------------+--------------------------------------+ $ mysql -uroot -e "SHOW GLOBAL STATUS LIKE 'wsrep_incoming%'\G" *************************** 1. row *************************** Variable_name: wsrep_incoming_addresses Value: 10.120.28.219:3306,10.120.29.124:3306
Важно. Когда вы отключаете узлы штатным способом, как сделали выше, кластер понимает, что общий вес кластера надо уменьшить (был 3/3, стал 2/2), поэтому состояние кластера считается целостным, а не деградированным. Если же узлы отключаются аварийно, то вес кластера не уменьшается (был 3/3, стал 2/3).
Проверка репликации данных
На одном из узлов создадим базу данных, таблицу и вставим данные в нее:
$ mysql -uroot MariaDB [(none)]> create database test; Query OK, 1 row affected (0.121 sec) MariaDB [(none)]> create table test.test (id INT PRIMARY KEY, name VARCHAR(32)); Query OK, 0 rows affected (0.195 sec) MariaDB [(none)]> insert into test.test values(1, "name"); Query OK, 1 row affected (0.003 sec)
Убедимся, что репликация произошла на оставшиеся узлы, выполнив на каждом из них команду запроса данных:
$ mysql -uroot -e 'select * from test.test;' +----+------+ | id | name | +----+------+ | 1 | name | +----+------+
Аналогичным образом вы можете осуществить проверку и для других операций.
Перезапуск кластера
Если каким-то образом все узлы кластера оказались выключены, вы должны повторить процедуру инициализации. Если серверы MariaDB будут запущены обычным образом, то сборка кластера не произойдет. Первый сервер вы должны запустить с помощью команды sudo galera_new_cluster
.
Теперь, когда ваш кластер работает вы можете захотеть повысить его сетевую безопасность за счет шифрования трафика между серверами Galera и между клиентами и кластером. Читайте об этом подробнее в нашем пошаговом руководстве по настройке SSL-шифрования в Galera.
Использование ClusterControl для развертывания и управления кластером Galera
Мы рассмотрели настройку кластера Galera в ручном режиме. Кроме этого подхода кластер Galera можно легко развернуть и обслуживать с помощью ClusterControl.
Если вы хотите развернуть кластер Galera с помощью ClusterControl, обратитесь к нашей статье на эту тему.