Представьте кластер из пяти узлов, разделённый сетью на группы из трёх и двух: какая группа может продолжать принимать согласованные записи при использовании консенсуса и почему?
Продолжать принимать согласованные записи может только группа из трёх узлов, потому что она сохраняет большинство кластера. Группа из двух узлов не может получить большинство, поэтому должна прекратить подтверждение новых записей, иначе при восстановлении связи возникнет риск двух несовместимых историй.
Протоколы консенсуса появились для согласованного выбора значения и порядка операций при отказах узлов и ненадёжной сети. Исходная проблема состоит в том, что узлы могут видеть разные состояния системы, а сообщения между ними могут задерживаться, теряться или приходить в другом порядке.
Большинство позволяет отделить безопасное продолжение работы от небезопасного. Любые два большинства в кластере пересекаются хотя бы одним узлом, поэтому две независимые стороны не могут одновременно легитимно зафиксировать конфликтующие решения при корректной работе протокола.
В кластере из пяти узлов большинство равно трём. После разделения сети группа из трёх узлов может связаться с лидером или выбрать нового лидера и зафиксировать запись, получив подтверждения большинства.
Группа из двух узлов не имеет достаточного числа голосов. Если разрешить ей подтверждать записи, обе группы смогут принимать изменения независимо, а после восстановления связи потребуется разрешать конфликт. Это может привести к потере подтверждённых данных, нарушению порядка операций или расхождению состояния реплик.
Важно различать безопасность и доступность. Отказ меньшинства сохраняет безопасность, но снижает доступность; попытка сохранить доступность меньшинства за счёт записи нарушает гарантию единой согласованной истории.
В большинстве протоколов консенсуса решение считается зафиксированным после подтверждения большинства узлов. Для пяти узлов это минимум три голоса. Поэтому группа из трёх узлов может продолжить работу, а группа из двух должна обслуживать только операции, не требующие фиксации нового общего состояния, либо возвращать ошибку.
При наличии лидера он обычно принимает запись, распространяет её участникам и считает её зафиксированной после получения подтверждений большинства. Если прежний лидер оказался в меньшей части, он не должен продолжать подтверждать записи: без большинства его действия не могут стать частью новой согласованной истории.
После восстановления связи узлы сравнивают служебные сведения о выбранной истории. Записи, которые существовали только в меньшинстве и не были зафиксированы большинством, могут быть отброшены или заменены актуальной историей лидера. Уже зафиксированные записи не должны быть отменены корректным протоколом.
Компромисс заключается в том, что такая схема жертвует доступностью при потере большинства ради безопасности. Если требуется принимать записи в обеих частях разделённого кластера, это уже не обычная строгая модель консенсуса, а система с более слабыми гарантиями или с последующим разрешением конфликтов.
Размер большинства зависит от числа узлов и модели отказов. В кластере из пяти узлов большинство из трёх позволяет пережить отказ или недоступность двух узлов, но не разделение, при котором ни одна сторона не содержит три узла.
Кластер хранения метаданных из пяти узлов разделился из-за отказа сетевого коммутатора. Три узла сохранили связь между собой, а два оказались изолированы, но продолжили принимать запросы от части клиентов.
Рассматривались два варианта. Разрешить запись обеим группам означало бы сохранить внешнюю доступность, но создало бы две конкурирующие истории и потребовало бы сложного разрешения конфликтов. Разрешить работу только группе из трёх узлов снижало доступность клиентов, подключённых к меньшей части, зато сохраняло единую линейную историю.
Выбрали второй вариант: группа из трёх узлов продолжила запись, а меньшая группа перевела операции изменения в режим ошибки или ожидания. После восстановления сети две изолированные реплики синхронизировались с актуальной историей. Результатом стало временное снижение доступности без потери согласованности.
1. Может ли группа из двух узлов читать данные во время разделения?
Это зависит от требуемой гарантии чтения. Она может обслуживать чтения локального состояния, если допустима потенциально устаревшая или не подтверждённая информация. Для строгого чтения, отражающего последнюю зафиксированную запись, узлу нужно доказать актуальность лидера и наличие действующего большинства; без этого безопаснее вернуть ошибку.
2. Что произойдёт, если группа из трёх узлов потеряет ещё один узел?
После потери узла останутся два из пяти, то есть большинство будет утрачено. Кластер должен прекратить фиксацию новых записей, даже если оставшиеся узлы продолжают видеть друг друга. Иначе система поставит доступность выше гарантии, что запись единственным образом войдёт в общую историю.
3. Достаточно ли физического большинства для защиты от разделения?
Нет. Важна не только численность узлов, но и корректная работа протокола: выбор лидера, номера эпох или терминов, фиксация записей большинством и запрет старому лидеру продолжать запись без кворума. Кроме того, узлы желательно размещать по независимым зонам отказа; пять узлов в одной стойке формально дают большинство, но общий отказ стойки лишает систему доступности.