Сейчас идёт тестирование: код на GitHub будет открыт после завершения.

Параметры Raft

ПараметрЗначение
Интервал heartbeat500 мс (cluster_heartbeat_ms)
Время признания недоступности2000 мс (cluster_election_timeout_ms) — если heartbeat отсутствует столько времени, лидер считается умершим
Фактический интервал начала выборов1750–2000 мс — на каждом узле разбрасывается случайно, чтобы исключить одновременное выдвижение кандидатов (split vote). Худшее значение равно как раз заданному времени признания недоступности
Простой клиента при отказе лидерапо замерам время признания недоступности + 0,3–0,5 с (при значениях по умолчанию около 2,3–2,5 с) — обнаружение плюс один редирект
Число узлов3 или 5 (принудительно проверяется при загрузке конфигурации — иное число блокирует запуск)
ID узлапозиция себя (cluster_self) в списке cluster_peers — поэтому порядок списка должен совпадать на всех узлах
Bootstrapчерез 500 мс после старта все узлы инициализируются с одинаковым составом участников; при присоединении к уже инициализированному кластеру игнорируется
Хранение логав памяти (энергозависимо) — перезапущенный узел восстанавливается через репликацию / снапшот
Обнаружение истечения leaseлидер обнаруживает с периодом 100 мс и фиксирует Expire через консенсус
Гранулярность таймаута waitтаймаут ожидания (T) тоже определяется на том же 100-мс тике — может прийти с задержкой до 100 мс
Уведомление о смене лидерапри смене лидера всем подключённым клиентам немедленно отправляется L

Как выбирать heartbeat и время признания недоступности

Оба значения настраиваются в конфигурации через cluster_heartbeat_ms и cluster_election_timeout_ms. Время признания недоступности (T) — это и есть время простоя сервиса при отказе лидера; и наоборот, слишком малое значение приводит к ложному признанию живого лидера умершим и лишним выборам.

heartbeat / TИнтервал обнаруженияХудшая задержка при отказе лидера (замер)Рекомендуемая среда
100 мс / 600 мс450–600 мсоколо 0,9 содна стойка / одна AZ, очень стабильные задержки
100 мс / 1000 мс750–1000 мсоколо 1,2 содна AZ
250 мс / 2500 мс1875–2500 мсоколо 2,8 снесколько AZ
500 мс / 2000 мс1750–2000 мсоколо 2,4 спо умолчанию — баланс для нескольких AZ
500 мс / 5000 мс3750–5000 мсоколо 5,3 смежрегиональные развёртывания, сильно скачущие задержки
  • На задержку в обычном режиме эти значения не влияют (замеренная p50 не меняется) — они определяют только время восстановления при отказе.
  • Отказ follower-узла ни при каких значениях не сказывается на клиентах. Указанные задержки возникают только при отказе лидера.
  • Ограничения: cluster_election_timeout_ms должен быть не менее 600 мс и не менее чем в 4 раза больше heartbeat. (Замерено, что одна задержка планировщика под нагрузкой способна целиком поглотить два heartbeat.)

Почему число узлов — 3 или 5

Для commit нужно большинство. Чётные конфигурации только увеличивают стоимость, не повышая отказоустойчивость, поэтому сервер их отклоняет.

Число узловБольшинствоДопустимые одновременные отказы
220 — остановка даже при отказе одного узла. Не лучше одиночного режима
321
431 — как у 3 узлов (только больше стоимость)
532

Сводка поведения при отказах

СитуацияПоведение
Клиентский запрос на нелидирующий узелM (адрес лидера), либо E no_leader, если лидер неизвестен
Отказ лидерановый лидер избирается в пределах заданного времени признания недоступности (по умолчанию 1750–2000 мс). В этот период запросы получают E no_leader → клиент повторяет попытку
Момент смены лидераожидавшие запросы захвата завершаются через M/E no_leader, клиент повторяет попытку на новом лидере
Перезапуск узластарт с пустым состоянием → догон через репликацию лога / снапшот от пиров
Потеря большинстваcommit невозможен → запись останавливается (безопасность прежде всего), автоматически возобновляется при восстановлении большинства

Термины

  • Кворум (quorum) — более половины всех узлов (2 из 3, 3 из 5). Любое решение фиксируется только при согласии кворума, поэтому две разделённые сетевым сбоем группы никогда не могут одновременно принять разные решения.
  • Таймаут выборов (election timeout) — время ожидания, по истечении которого follower считает, что лидер умер (если за это время не было heartbeat), и начинает выборы. У каждого узла оно случайно отличается, что снижает вероятность одновременного перехода нескольких узлов в кандидаты.