Как сервера договариваются друг с другом: алгоритм распределённого консенсуса Raft

Рассмотрим следующую ситуацию: три сервера в кластере. Сервер S1 — лидер текущего первого срока. Все серверы имеют по три записи в логе.

g6c9zbx5fsewp_4nn0komxcnikm.png

Лидер S1 получает запрос от клиента и добавляет в свой лог новую запись, отправляет AppendEntries другим серверам S2 и S3.

rzkigfvgmygzxg4qbwy9tfgf914.png

До S2 запись успешно доходит, но сеть между S1 и S3 моргает, и запрос теряется. Поскольку S1 знает, что запись присутствует на двух серверах из трёх, он может определить, что запись закоммичена, и ответить клиенту успехом.

S1 также будет ретраить добавление записи на S3 до тех пора, пока у него не получится. Но что будет, если с S1 произойдёт сбой и он отключится? Более того, что будет, если S3 первым надоест ждать, и он станет кандидатом? S2 за него проголосует, S3 станет лидером второго срока, и при следующем запросе на добавление записи, S3 перезапишет нашу закоммиченную запись?

_gijl3pklfn6g5xme0ta7-svaus.png

На самом же деле такая ситуация не может произойти в кластере Raft. Подвох здесь в том, что S2 не стал бы голосовать за S3. Почему? Потому что лог сервера S3 на момент голосования менее актуален, чем лог сервера S2. Этот механизм называется Election restriction — сервер будет голосовать за другой сервер, только если лог кандидата не менее актуален, чем лог голосующего.

Raft сравнивает актуальность логов по двум параметрам:

  • Номер срока последней записи
  • Длина лога


Эти два параметра кандидаты включают в запрос «RequestVote», чтобы фоловеры могли сравнить актуальность своего лога с логом кандидата.

«Главнее» тот лог, в котором старше срок последней записи.

7o2a-vpncoa6z4qwmn-xdgckh1m.png

Если же номера срока последних записей совпадают, то «главнее» тот лог, который длиннее.

qfkxnk-qv4py6t6lvw3i8wuphu4.png

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

hpejx8hkcwkm-fjs7qs98gzn8pc.png

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

© Habrahabr.ru