Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Raft: алгоритм консенсуса в распределенных системах

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

Алгоритм Raft: роли leader/follower/candidate, термы, выборы лидера, репликация лога и безопасность — разбор с примерами etcd и Patroni.

Прямой ответ

Raft — алгоритм консенсуса, который позволяет группе узлов договориться о последовательности записей даже при отказах части узлов. Он спроектирован как понятная альтернатива Paxos: та же задача, но декомпозированная на три подзадачи — выборы лидера, репликация лога и безопасность. Классическая конфигурация — нечётное число узлов (3, 5, 7): кворум составляет большинство, поэтому при отказе меньшинства кластер продолжает принимать записи, а при разделении сети меньшая сторона просто перестаёт обслуживать запись — это базовая защита от split brain.

Ключевые понятия:

  • Роли. Каждый узел находится в одном из трёх состояний: leader, follower, candidate. В любой момент терма не более одного лидера; все записи идут через него, а followers лишь отвечают на запросы.
  • Терм (term). Логический «эпохальный» счётчик. Каждые выборы увеличивают терм. Если узел получает сообщение с более высоким термом, он немедленно переходит в follower — так кластер избавляется от устаревших лидеров.
  • Выборы лидера. Если follower не получил heartbeat от лидера за election timeout (в эталонной реализации — случайное значение в диапазоне 150–300 мс), он становится кандидатом, увеличивает терм и рассылает RequestVote. Побеждает кандидат, набравший большинство голосов; узел голосует не более одного раза за терм.
  • Репликация лога. Лидер принимает команды клиентов, добавляет их в свой лог и рассылает AppendEntries. Когда запись скопирована на большинство узлов, она считается зафиксированной (committed) и применяется к состоянию.
  • Ограничение выбора лидера. Кандидат получает голос только если его лог не менее актуален, чем лог голосующего (сравнение по индексу и терму последней записи). Это гарантирует, что зафиксированные записи не потеряются после смены лидера.

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

Практика: где Raft работает в вашем стеке

etcd. Хранилище конфигурации Kubernetes использует Raft для согласованности ключ-значение; etcd прямо рекомендует нечётное число участников и предупреждает, что потеря кворума делает кластер недоступным для записи.

Patroni. Надстройка для PostgreSQL использует распределённое хранилище (etcd/Consul/ZooKeeper) как DCS: лидер держит ключ с TTL, а при его исчезновении узлы устраивают гонку за лидерство — подробнее в статье про автоматический failover PostgreSQL.

Consul, TiKV, CockroachDB, Kafka (KRaft). В Kafka контроллеры с версии 3.x работают в режиме KRaft, где метаданные кластера хранятся в Raft-логе вместо ZooKeeper — это упрощает эксплуатацию и ускоряет восстановление.

Что настраивать на практике:

  1. Число узлов. Три узла выдерживают отказ одного, пять — двух. Чётное число не добавляет отказоустойчивости, но увеличивает задержку кворума.
  2. Разнесение по зонам. Узлы должны жить в разных стойках/зонах; иначе отказ одной зоны уносит кворум целиком.
  3. Тайминги. election timeout должен заметно превышать RTT и время fsync на диске. На медленных дисках слишком агрессивный таймаут приводит к «выборам вхолостую» и просадкам записи.
  4. Снимки (snapshots). Лог Raft бесконечно растёт, поэтому узлы периодически сохраняют снапшот состояния и обрезают лог. Следите за размером снапшота: слишком большой — долгая отправка новому узлу, слишком частая генерация — лишняя нагрузка на диск.

Практический сценарий: кластер из трёх узлов теряет лидера

Контекст: etcd из трёх узлов в трёх зонах обслуживает конфигурацию сервиса; один узел упал вместе с зоной.

  1. Детекция. Followers не получают heartbeat. Через election timeout оба становятся кандидатами; случайный разброс таймаута почти всегда предотвращает одновременную победу.
  2. Выборы. Один кандидат собирает 2 голоса из 3 (большинство), становится лидером нового терма и возобновляет запись. Второй кандидат видит более высокий терм и возвращается в follower.
  3. Проверка лога. Новый лидер сравнивает логи и дописывает недостающие записи на follower — зафиксированные записи при этом не теряются.
  4. Наблюдаемость. На дашборде видно всплеск etcd_server_leader_changes_seen_total и кратковременный рост задержки записи; алерт на частые смены лидера — признак проблем с диском или сетью, а не «нормальной жизни» кластера. Как строить такие алерты — в статье про правила оповещения Alertmanager.
  5. Восстановление. Узел возвращается, получает снапшот и недостающий лог, догоняет кластер.

Результат: недоступность записи длилась секунды, данные не потеряны. Вывод: Raft корректно обработал отказ, потому что кворум (2 из 3) сохранился; если бы упали две зоны, кластер стал бы только читаемым/недоступным — и это ожидаемое поведение, а не баг.

FAQ

Чем Raft отличается от Paxos? Оба решают задачу консенсуса, но Raft жёстко структурирован: сильный лидер, явные термы, правило актуальности лога. Paxos (особенно Multi-Paxos) допускает больше свободы в реализации, из-за чего корректные реализации сложнее писать и проверять. На практике Raft выбирают, когда важна понятность и предсказуемость поведения, — сравнение подходов — в статье про Paxos.

Сколько узлов нужно и что будет при потере одного? Минимум три. Кворум для трёх — два, поэтому отказ одного узла не прерывает запись. Для пяти узлов кворум — три, то есть допустимы два отказа. Чётное число (например, четыре) даёт кворум три — ту же отказоустойчивость, что и три узла, но с лишней нагрузкой.

Можно ли читать данные с follower без потери согласованности? Наивное чтение с follower может вернуть устаревшее значение. Для строгой согласованности чтение должно проходить через лидера либо использовать механизм ReadIndex/lease read, при котором лидер подтверждает своё лидерство кворумом перед ответом. Слабые чтения с реплик — осознанный компромисс, описанный в материале про модели согласованности.

Как Raft защищает от split brain? Любое решение требует большинства голосов. При разделении сети две половины не могут одновременно набрать большинство, поэтому лидером остаётся только узел в «мажоритарной» части. Меньшая сторона отклоняет запись до восстановления связности — детали и смежные сценарии разобраны в статье про split brain.

Источники: raft.github.io (спецификация Raft), etcd.io/docs (рекомендации по кластеру), Patroni docs — ссылки в шапке.