Восстановление кластера

Если репликационный узел или весь кластер становится недоступным, правильная процедура восстановления зависит от того, сколько узлов остаются доступными и был ли останов чистым или внезапным.

Репликационный кластер следует рассматривать как одну логическую систему, а не набор независимых серверов. Это обеспечивает многомастерные записи и согласованность данных, но также означает, что вы должны осторожно восстанавливать кворум. В частности, не запускайте команду ручного восстановления, которая восстанавливает записи на сохранившейся стороне, пока не убедитесь, что пропавшие узлы действительно отсутствуют. Эта команда показана далее на этой странице как SET CLUSTER <name> GLOBAL 'pc.bootstrap' = 1. Если запустить её слишком рано, можно создать расщепление мозга и получить два независимых кластера.

Для примеров ниже предполагается кластер с узлами A, B и C, если не указано иначе.

Прежде чем восстанавливать что-либо

Сначала определите, в какой ситуации вы находитесь:

  • Есть хотя бы один узел онлайн?
  • Узел был остановлен чисто или он упал? Чистая остановка означает, что searchd был остановлен нормально и имел время сохранить состояние репликации перед выходом. Падение, потеря питания или kill -9 не являются чистой остановкой.
  • Сохранившаяся часть кластера ещё имеет кворум? Кворум означает, что достаточно узлов могут видеть друг друга, чтобы безопасно оставаться кластером с возможностью записи.
  • Если все узлы отключены, какой узел следует запустить первым для восстановления кластера?

Полезные проверки:

  • SHOW STATUS LIKE 'cluster_<name>_status'
  • SHOW STATUS LIKE 'cluster_<name>_size'
  • SHOW STATUS LIKE 'cluster_<name>_node_state'
  • если все узлы отключены, проверьте grastate.dat, небольшой файл состояния репликации, хранящийся в директории данных кластера. Особенно обратите внимание на seqno и safe_to_bootstrap: при чистой остановке лучший узел для запуска первым обычно тот, с наиболее продвинутым seqno и safe_to_bootstrap: 1. Для полной процедуры bootstrap см. Перезапуск кластера.

Пример того, как grastate.dat может выглядеть после чистой остановки:

# saved replication state
version: 2.1
uuid:    <cluster-uuid>
seqno:   12345
safe_to_bootstrap: 1

В этом примере:

  • seqno: 12345 означает, что этот узел знает о транзакциях до порядкового номер 12345
  • safe_to_bootstrap: 1 означает, что этот узел помечен как безопасный для запуска первым

При чистом восстановлении после остановки всех узлов, это обычно тот тип узла, который вы запускаете первым с --new-cluster для восстановления кластера.

После восстановления, дождитесь, пока перезапущенный узел сообщает cluster_<name>_status=primary и cluster_<name>_node_state=synced, прежде чем считать его полностью доступным для записи. Это можно проверить с помощью SHOW STATUS LIKE 'cluster_<name>_status' и SHOW STATUS LIKE 'cluster_<name>_node_state'. В локальных тестах перезапущенные узлы иногда некоторое время находились в состоянии cluster_<name>_node_state=joining и cluster_<name>_status=disconnected перед достижением synced/primary.

Один узел был остановлен чисто

Если узел A остановлен нормально, узлы B и C продолжают обслуживать записи. Вы можете подтвердить, что кластер всё ещё здоров на этих узлах с помощью SHOW STATUS LIKE 'cluster_<name>_status' и SHOW STATUS LIKE 'cluster_<name>_size'.

Когда узел A запускается снова, он автоматически присоединяется к кластеру. До завершения синхронизации не отправляйте записи на этот узел. Проверьте SHOW STATUS LIKE 'cluster_<name>_status' и SHOW STATUS LIKE 'cluster_<name>_node_state' и дождитесь primary / synced.

Если узлы-доноры B или C ещё имеют все транзакции, которые узел A пропустил, в своём репликационном кэше, узел A может догнать их с помощью инкрементного переноса состояния (IST). IST означает инкрементный перенос состояния. Это означает, что узел получает только транзакции, которые он пропустил, поэтому восстановление обычно быстрее и легче. В противном случае потребуется перенос состояния через снимок (SST). SST означает перенос состояния через снимок. Это означает копирование файлов таблиц из другого узла вместо простого воспроизведения пропущенных транзакций. SST более тяжелый: обычно он медленнее, перемещает больше данных и может сделать восстановление более разрушительным на больших кластерах.

Два узла были остановлены чисто и один узел остался онлайн

Если узлы A и B остановлены чисто и узел C остаётся онлайн, узел C может продолжать принимать записи. Проверьте SHOW STATUS LIKE 'cluster_<name>_status' и SHOW STATUS LIKE 'cluster_<name>_size' на узле C, если хотите подтвердить, что он теперь единственный активный узел.

Когда узлы A и B запускаются снова, они автоматически присоединяются и синхронизируются с узлом C. Во время присоединения проверьте SHOW STATUS LIKE 'cluster_<name>_status', SHOW STATUS LIKE 'cluster_<name>_node_state', и SHOW STATUS LIKE 'cluster_<name>_size'. Дождитесь, пока все узлы показывают primary / synced и ожидаемый размер кластера, прежде чем считать восстановление завершенным.

Все узлы были остановлены чисто

Если все узлы были остановлены нормально, кластер полностью отключен и должен быть запущен снова специальным образом, чтобы он мог стать первым работающим узлом кластера.

При чистой остановке каждый узел записывает свой последний номер транзакции в grastate.dat. Узел, который был остановлен последним, является самым безопасным узлом для запуска первым:

  • он имеет наиболее продвинутый seqno
  • он имеет safe_to_bootstrap: 1

Запустите этот узел с --new-cluster. Это указывает Manticore запустить новую копию кластера с этого узла. Если вы запускаете Manticore через systemd в Linux, используйте manticore_new_cluster. Он запускает Manticore в режиме --new-cluster за вас.

После этого запустите остальные узлы нормально и позвольте им присоединиться. Проверьте восстановление с помощью SHOW STATUS LIKE 'cluster_<name>_status', SHOW STATUS LIKE 'cluster_<name>_node_state', и SHOW STATUS LIKE 'cluster_<name>_size'.

Если вы запустите менее продвинутый узел первым, более продвинутый узел позже присоединится к нему и получит полный SST из более старого состояния, что может отбросить транзакции, которые существовали только на более продвинутом узле. Поэтому узел с safe_to_bootstrap: 1 должен быть вашим первым выбором.

Один узел упал или стал недоступным

Если узел A исчезает из-за сбоя или сетевой проблемы, узлы B и C сначала попытаются переподключиться к нему. Если это не удается, они удаляют его из кластера, пересчитывают кворум и продолжают работать как основной кластер.

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

Когда узел A снова запускается, он автоматически присоединяется и наверстывает упущенное так же, как после чистого завершения работы одного узла. Снова используйте SHOW STATUS LIKE 'cluster_<name>_status', SHOW STATUS LIKE 'cluster_<name>_node_state' и SHOW STATUS LIKE 'cluster_<name>_size', чтобы подтвердить завершение восстановления.

Два узла потеряны, и работает только один узел

Если узлы A и B потеряны, и работает только узел C, узел C больше не имеет кворума в трехузловом кластере. Он переключается в состояние non-primary и отклоняет запись.

Ошибка записи явная:

ERROR 1064 (42000): cluster '<name>' is not ready, not primary state (synced)

Если узлы A и B только временно отключены, но все еще могут видеть друг друга, они могут продолжать принимать записи, в то время как узел C остается изолированным. Используйте SHOW STATUS LIKE 'cluster_<name>_status' на каждой стороне, если вам нужно увидеть, какая сторона все еще доступна для записи.

Если узлы A и B действительно аварийно завершили работу, а узел C — единственная сохранившаяся копия, с которой вы хотите продолжать работать, выполните эту команду на узле C, чтобы снова сделать его доступным для записи:

Если вы подтвердили, что другие узлы действительно отключены, выполните:

‹›
  • SQL
  • JSON
📋
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1

Важно:

  • выполняйте это только после того, как убедитесь, что другие узлы недостижимы
  • выполняйте это только на стороне, которая должна выжить
  • после начальной загрузки узел снова может принимать записи, и другие узлы позже смогут к нему повторно присоединиться

Все узлы аварийно завершили работу

Если каждый узел аварийно завершил работу, grastate.dat, как правило, больше не заслуживает доверия для обычного выбора начальной загрузки. В локальных тестах все узлы показывали:

  • seqno: -1
  • safe_to_bootstrap: 0

В этой ситуации выберите узел с самыми свежими данными и запустите его с --new-cluster-force. Это заставляет Manticore запустить новую копию кластера с этого узла, даже несмотря на то, что обычные метаданные чистого завершения работы не заслуживают доверия. Если вы запускаете Manticore через systemd в Linux, используйте manticore_new_cluster --force. Он запускает Manticore в режиме --new-cluster-force для вас.

Затем запустите оставшиеся узлы в обычном режиме и позвольте им повторно присоединиться. Проверьте восстановление с помощью SHOW STATUS LIKE 'cluster_<name>_status', SHOW STATUS LIKE 'cluster_<name>_node_state' и SHOW STATUS LIKE 'cluster_<name>_size'.

Кластер с четным числом узлов потерял кворум, например, после разделения

Риск разделения мозга наиболее высок в кластерах с четным числом узлов. Например, представьте четыре узла, разделенных на две изолированные пары в двух центрах обработки данных. Каждая сторона имеет ровно половину от исходного числа участников, поэтому ни одна из сторон не имеет кворума, и обе стороны прекращают принимать записи.

Если вам необходимо восстановить запись до устранения проблемы с подключением, выберите только одну сторону разделения и выполните ту же команду восстановления там, чтобы эта сторона снова стала доступной для записи. Перед этим проверьте SHOW STATUS LIKE 'cluster_<name>_status' на обеих сторонах, чтобы знать, какая сторона в настоящее время является неосновной.

Выберите сторону, которая должна остаться доступным для записи кластером, затем выполните:

‹›
  • SQL
  • JSON
📋
SET CLUSTER posts GLOBAL 'pc.bootstrap' = 1

Никогда не выполняйте этот оператор на обеих сторонах. Если вы это сделаете, вы создадите два отдельных основных кластера, и они не объединятся автоматически при восстановлении сети.

В локальном тестировании внезапная потеря половины четырехузлового кластера воспроизвела то же поведение non-primary, и та же команда восстановления вернула одну выжившую половину в состояние primary.

Last modified: May 22, 2026