Автоматический выбор лидера
В Tarantool, начиная с версии 2.6.1, есть встроенный механизм управления автоматическими выборами лидера (automated leader election) в наборе реплик (replica set). Этот механизм повышает отказоустойчивость систем на базе Tarantool и снижает зависимость от внешних инструментов для управления набором реплик.
Подробнее о настройке и мониторинге автоматических выборов лидера см. в разделе Управление выборами лидера.
Ниже описаны следующие темы:
Выборы лидера и синхронная репликация реализованы в Tarantool как модификация алгоритма Raft. Raft — это алгоритм синхронной репликации и автоматических выборов лидера. Полное описание алгоритма Raft можно прочитать в соответствующем документе.
Синхронная репликация и выборы лидера в Tarantool реализованы как две независимые подсистемы. Это означает, что можно настроить синхронную репликацию, а для выборов лидера использовать альтернативный алгоритм. Встроенный механизм выборов лидера, в свою очередь, не требует синхронных спейсов. Синхронной репликации посвящен этот раздел документации. Процесс выборов лидера описан ниже.
Автоматические выборы лидера в Tarantool гарантируют, что в любой момент времени в наборе реплик будет максимум один лидер – узел, доступный для записи. Все остальные узлы будут принимать исключительно запросы на чтение.
Когда функция выборов включена, жизненный цикл набора реплик разделен на так называемые термы (term). Каждый терм описывается монотонно растущим числом. После первой загрузки узла значение его терма равно 1. Когда узел видит, что не является лидером и при этом лидера в наборе реплик уже какое-то время нет, он увеличивает значение своего терма и начинает новый тур выборов.
Выборы лидера проходят путём голосования. Узел, начинающий выборы, голосует сам за себя и отправляет другим запросы на голос. Каждый экземпляр голосует за первый узел, от которого пришел такой запрос, и далее в течение всего терма ожидает избрания лидера, не выполняя никаких действий.
Узел, собравший кворум голосов, заданный параметром replication.synchro_quorum, становится лидером и уведомляет об этом остальные узлы. Также возможна ситуация разделенного голосования, когда ни один узел не набирает кворум голосов. В этом случае по истечении случайного времени ожидания каждый узел увеличивает значение своего терма и начинает новый тур выборов, если за это время не поступит новый запрос на голосование с большим значением терма. В итоге один из узлов будет назначен лидером.
Если от предыдущего лидера остались незавершенные синхронные транзакции, новый лидер завершает их автоматически.
Все узлы, не являющиеся лидерами, называются последователями (followers). Узлы, начинающие новый тур выборов, называются кандидатами (candidates). Избранный лидер отправляет сигналы активности (heartbeats) остальным узлам, чтобы сообщить, что он работает.
Если сигналы активности не поступают в течение replication.timeout * 4, узел, не являющийся лидером, начинает новые выборы при соблюдении следующих условий:
- Узел имеет кворум соединений с другими членами кластера.
- Ни один из этих членов кластера не видит узел-лидер.
Термы и голоса сохраняются каждым экземпляром на диске для сохранения определенных гарантий алгоритма Raft.
При голосовании узлы предпочитают экземпляры, где сохранены самые новые данные. Поэтому, если прежний лидер перед тем, как стать недоступным, отправит кворуму реплик какую-либо информацию, она не будет потеряна.
При включенных выборах между каждой парой узлов должно быть установлено соединение, то есть должна использоваться полносвязная ячеистая топология. Это необходимо, поскольку сообщения выборов для голосования и других внутренних операций требуют прямого соединения между узлами.
В классическом алгоритме Raft лидер не отслеживает свою связность с остальной частью кластера. После избрания лидер считает себя лидером до тех пор, пока не получит новое значение терма от другого узла кластера. Это может привести к ситуации разделения, если остальные узлы выберут нового лидера при потере связности с предыдущим.
Эта проблема решена в Tarantool версии 2.10.0 введением режима ограждения (fencing) лидера. Режим переключается с
помощью параметра
replication.election_fencing_mode.
Если установлено значение soft или strict, лидер отказывается от своей роли, если количество активных соединений с
узлами кластера становится меньше значения
replication.synchro_quorum.
Лидер, отказавшийся от роли, получает статус последователя в текущем терме выборов и переходит в режим только для
чтения. Режим ограждения лидера можно отключить, установив значение off для параметра
replication.election_fencing_mode.
В режиме soft соединение считается разорванным, если ответы отсутствуют в течение
4 * replication.timeout
секунд как на текущем лидере, так и на последователях.
В режиме strict соединение считается разорванным, если ответы отсутствуют в течение
2 * replication.timeout
секунд на текущем лидере и в течение
4 * replication.timeout
секунд на последователях. Это повышает вероятность, что в любой момент времени существует только один лидер.
Ограждение применяется к экземплярам, для которых параметр
replication.election_mode
установлен в candidate или manual.
Тем не менее возможна ситуация, когда в наборе реплик есть два лидера, работающих независимо (так называемый
split-brain). Это может произойти, например, если пользователь по ошибке задал для параметра
replication.synchro_quorum
значение меньше N / 2 + 1. В такой ситуации для сохранения целостности данных при обнаружении аномалии split-brain во
входящих данных репликации экземпляр разрывает соединение с экземпляром, отправляющим данные, и записывает ошибку
ER_SPLIT_BRAIN в журнал.
В итоге образуются два набора узлов с расходящимися данными, и любой узел из одного набора отключен от любого узла из
другого набора с ошибкой ER_SPLIT_BRAIN.
Заметив ошибку, пользователь может выбрать любой узел из каждого набора и проверить данные на них. Для согласования данных следует удалить их с узлов одного набора и подключить эти узлы к узлам из другого набора, на которых находятся корректные данные.
Любой узел, участвующий в выборах, реплицирует данные только с последнего избранного лидера. Это позволяет избежать ситуации, в которой прежний лидер после выборов нового все еще пытается отправлять изменения на реплики.
Числовые значения термов также служат своеобразным фильтром. Например, если на двух узлах включена функция выборов и
значение терма node1 меньше значения терма node2, то узел node2 не будет принимать транзакций от узла node1.
replication:election_mode: <string>election_fencing_mode: <string>election_timeout: <seconds>timeout: <seconds>synchro_quorum: <count>
- replication.election_mode – определяет роль узла в выборах лидера.
- replication.election_fencing_mode – определяет режим ограждения лидера.
- replication.election_timeout – задает время ожидания между турами выборов, если предыдущий тур завершился разделенным голосованием.
- replication.timeout – интервал времени (в секундах), через который мастер отправляет сигналы активности реплике, если для нее нет обновлений.
- replication.synchro_quorum – количество реплик, которые должны подтвердить получение синхронной транзакции для завершения ее коммита.
Важно знать, что статус лидера – не единственное условие, чтобы узел был доступен для записи. Лидер также должен соответствовать следующим требованиям:
-
Параметр database.mode установлен в значение
rw. -
Лидер не должен находиться в состоянии
orphan. Параметрdatabase.modeможно установить в значениеro, но тогда лидер не будет доступен для записи. Этот параметр не влияет на сами выборы, поэтому экземпляр в режиме только для чтения может голосовать и стать лидером.
Для мониторинга текущего состояния узла при выборах лидера используйте функцию box.info.election.
Пример:
tarantool> box.info.election---- state: followervote: 0leader: 0term: 1...
Реализация выборов на основе алгоритма Raft записывает все свои действия в журнал с префиксом RAFT:. К таким действиям
относятся обработка новых сообщений Raft, изменение состояния узла, голосование и увеличение значения терма.
Выборы лидера работают некорректно, если кворум выборов установлен в значение, меньшее или равное
<размер кластера> / 2. В этом случае разделенное голосование может привести к ситуации, когда одновременно избираются
два лидера.
Например, предположим, что есть пять узлов. При кворуме, равном 2, node1 и node2 могут оба проголосовать за
node1. node3 и node4 могут оба проголосовать за node5. В этом случае node1 и node5 оба выигрывают выборы.
Если кворум установлен в значение большинства кластера, то есть (<размер кластера> / 2) + 1 или больше, разделенное
голосование невозможно.
Это следует учитывать при добавлении новых узлов. Если значение большинства изменяется, перед добавлением нового узла рекомендуется обновить значение кворума на всех существующих узлах.
Кроме того, автоматические выборы лидера не дают существенных преимуществ для сохранности данных при использовании без синхронной репликации. Если репликация асинхронная и выбран новый лидер, прежний лидер остается активным и считает себя лидером. В этом случае ничто не мешает ему принимать запросы от клиентов и выполнять транзакции. Несинхронные транзакции успешно коммитятся, так как они не проверяются по кворуму реплик. Синхронные транзакции завершаются с ошибкой, так как не могут собрать кворум – большинство реплик отклоняют транзакции прежнего лидера, поскольку он больше не является лидером.