Кластеры Galera из двух узлов

Это перевод статьи: Two-Node Clusters.

Введение

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

Вне зависимости от причины, при наличии лишь двух узлов необходимо учесть некоторые особенности и принять соответствующие меры. В кластере из двух узлов конфликт транзакций может привести к расщеплению кластера, а при сбое одного узла другой узел перейдёт в нерабочее состояние. В этой статье объясняется, как предупредить подобные ситуации.

Два сценария

В этой статье будет рассмотрено два сценария. В первом сценарии решается проблема с конфликтом транзакций в кластере из двух узлов. Предположим, что каждый из узлов выполняет транзакцию, которая меняет одну и ту же строку в одной и той же таблице в одно и то же время. Каждый узел голосует за свою транзакцию. Обычно решающий голос имеет третий узел. Без этого решающего голоса каждый узел фиксирует свою конфликтующую транзакцию. Такая ситуация называется расщеплением. По мере дальнейших транзакций происходит больше конфликтов, т.к. отличия в данных продолжат расти.

Во втором сценарии предпологается, что один из двух узлов внезапно покинул кластер. Например, он аварийно завершил работу или стал недоступен по сети. В таком случае другой узел переходит в нерабочее состояние. Он остаётся таким до поступления дополнительной информации - подключения другого узла или вмешательства администратора.

Почему узел спереходит в нерабочее состояние? Если один из узлов отделился от кластера из-за недоступности по сети, то оба узла могут посчитать себя первичным компонентом. Каждый не знает о том, что другой продолжает работать. В таком случае узлы не смогут согласовать различия в данных после восстановления связи. Чтобы предотвратить это, работающий узел переходит в нерабочее состояние.

Рекомендации для первого сценария

Рассмотрим, как решить возможную проблему из описанного выше первого сценария, в котором есть конфликт транзакций, но нет решающего голоса. Простейшее решение - использовать арбитр Galera. Он может быть членом кластера и участвовать в голосовании, но не в репликации данных. У арбитра есть собственный демон - garbd, отдельный от демона mysqld.

Арбитра Galera можно запустить либо с указанием нескольких опций командной строки, либо с указанием файла конфигурации. Имя файла конфигурации и его местоположение не имеют значения. Например, можно назвать его garbd.cnf и поместить в каталог /etc, где находятся файлы конфигурации базы данных. Ниже приведён пример файла конфигурации арбитра:

group="galera-testing"
address="gcomm://172.31.30.39,172.31.18.53,172.31.26.106"
options="gmcast.listen_addr=tcp://0.0.0.0:4444"
log="/var/log/garbd.log"

Для опции group нужно использовать значение, совпадающее со значением опции wsrep_cluster_name в файле конфигурации базы данных. Опция address должна совпадать со значением, указанном в опции wsrep_cluster_address. Опция log указывает полное имя файла журнала.

Нужно создать одинаковые файлы конфигурации на каждом узле, поскольку нельзя угадать, какой из узлов может сломаться. Для запуска арбитра Galera с файлом конфигруации можно воспользоваться командой следующего вида:

garbd --cfg /etc/garbd.cnf

Демон garbd запустится с опциями из указанного файла конфигурации. К командной строке можно добавить другие опции. Нужно сделать это на каждом из узлов. Демоны garbd будут работать по сети, как единое целое. Если один из двух узлов кластера выйдет из строя, оставшийся узел вмесете с демоном garbd продолжат работать, поскольку у узла есть арбитр.

Рекомендации для второго сценария

Для решения возможной проблемы из второго описанного выше сценария вместо использования арбитра Galera можно превратить один из оставшихся в строю узлов в первичный компонент. Это можно сделать с помощью опции pc.boostrap провайдера wsrep. Для этого подключитесь к узлу с помощью клиента mysql и выполните следующее выражение SQL:

SET GLOBAL wsrep_provider_options='pc.bootstrap=YES';

Оставшийся в строю узел станет новым первичным компонентом. Когда другие узлы восстановят работу или восстановят связь с этим узлом, они поймут, что отстают от него и запросят у него передачу состояния, чтобы синхронизироваться с ним.

Другое решение - ещё хуже - настроить параметр wsrep_provider_options. Можно воспользоваться им для включения pc.ignore_sb, который разрешает продолжать работать независимо. Для этого нужно подключиться к узлу с помощью клиента mysql и выполнить следующее выражение SQL:

SET GLOBAL wsrep_provider_options='pc.ignore_sb=TRUE';

Узел продолжит обрабатывать обновления, даже если существует вероятность расщепления кластера. Включать pc.ignore_sb в кластере с несколькими ведущими узлами опасно, потому что это приведёт к риску расщепления кластера. Однако кластеры с ведущими и ведомыми узлами от этого становятся проще - особенно если есть всего два узла.