Что такое проблема split-brain в кластере master-failover и как с ней бороться
Что проверяют
Понимает ли кандидат, что автоматическое переключение на резерв это не «поднять запасной узел», а задача согласия в сети, которая умеет врать. От бэкендера на Go ждут не пересказа теории, а ответа на вопрос, как ведёт себя его сервис, когда решил, что он лидер, и когда это уже перестало быть правдой.
Как отвечать
Определение: split-brain это состояние, при котором после разрыва связи две части кластера независимо считают себя главными и обе принимают записи. Дальше расхождение данных, которое автоматическим слиянием не лечится.
Механизмы защиты по значимости: кворум большинства при нечётном числе голосующих, из-за чего меньшая часть сама уходит в режим только на чтение; внешний сервис консенсуса или арбитр вместо голосования самих узлов; лидерская аренда с ограниченным сроком, который короче таймаута обнаружения сбоя; отсечение старого мастера, то есть отключение его от хранилища или отказ принимать его записи по номеру эпохи.
// хранилище отвергает запись от лидера прошлой эпохи
if req.Epoch < store.CurrentEpoch() {
return ErrStaleLeader
}Где спотыкаются
Считают, что кворума достаточно. Кворум решает, кто новый лидер, но не останавливает старого: отрезанный узел ещё держит клиентские соединения и принимает записи, пока не узнал новость. Без отсечения или аренды данные всё равно разъедутся.
Собирают кластер из двух узлов. При разрыве большинства не соберёт никто, а если разрешить повышение по факту недоступности соседа, получатся два мастера сразу. Нужен третий голос, пусть это будет лёгкий арбитр без данных.
Забывают, что процесс способен замереть: длинная пауза сборщика мусора, своп, заморозка виртуальной машины. Такой лидер просыпается уверенным в своих правах и продолжает писать по истёкшему токену. Поэтому право на запись проверяется перед операцией по живой аренде, а не хранится в булевой переменной, выставленной когда-то при выборах.