awesome-everything EN
↑ Обратно к восхождению

Распределённые системы

Raft в production: membership change, Multi-Raft и observability

Суть Joint consensus для безопасного membership change, паттерны Multi-Raft шардирования, leadership transfer для rolling deploy, минимально жизнеспособный Raft dashboard и три реальных production postmortem.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 16 min

Нужно заменить мёртвую ноду в 3-нодовом etcd-кластере. “Просто удали её и добавь новую” звучит просто — но сделано неправильно, это может оставить две группы нод, каждая из которых считает себя большинством. Joint consensus создан именно для предотвращения этого.

Membership change через joint consensus

Добавление или удаление нод из работающего Raft-кластера — самая error-prone операция в production. Наивный подход — атомарно поменять конфиг на всех нодах — создаёт окно несоответствия, в котором могут одновременно существовать два отдельных большинства.

Пример бага: переход с 3 нод (A, B, C) на 5 нод (A, B, C, D, E). Если разные ноды применяют смену конфига в разное время, можно ненадолго иметь: большинство старого конфига (2 из A, B, C) и большинство нового конфига (3 из A, B, C, D, E). Эти два большинства могут иметь нулевое пересечение — два лидера могут быть выбраны одновременно.

Joint consensus фиксит это: кластер переходит через промежуточную конфигурацию C_old_new, требующую большинства и от старой, и от новой конфигурации. Коммиты в этой фазе требуют большинства C_old И большинства C_new. Никакие два валидных кворума в этом окне не могут не пересекаться. Как только C_old_new закоммичено по всему кластеру, кластер переходит в C_new.

Hashicorp Raft и etcd реализуют joint consensus с дополнительным упрощением: только single-server изменения (добавлять или удалять по одной ноде). Это ограничивает joint-фазу простым двойным требованием большинства. Никогда не обходи joint consensus при membership change в production — Alibaba Cloud Raft engineering post документирует реальный 30-минутный split brain именно из-за этого сокращения.

ФазаКонфигурацияПравило кворума
ДоC_old: A, B, CБольшинство C_old (2 из 3)
ПереходC_old_newБольшинство C_old И большинство C_new
ПослеC_new: A, B, C, D, EБольшинство C_new (3 из 5)

Leadership transfer для rolling deploy

Без явного leadership transfer дрейнирование ноды-лидера перед обслуживанием вызывает одни выборы (150–300 мс недоступности) на каждую смену лидера. В Multi-Raft-системе с тысячами групп это неприемлемо.

TimeoutNow решает это: текущий лидер шлёт сообщение TimeoutNow назначенному целевому follower-у, который немедленно стартует выборы. Поскольку никакой другой follower ещё не таймаутил, цель почти всегда побеждает. Текущий лидер понижается. Пользователь-видимая недоступность — под 10 мс. CockroachDB и TiKV expose-ят leadership-transfer endpoint-ы именно для rolling deploy.

Multi-Raft и шардирование

Throughput одной Raft-группы ограничен fsync самой медленной реплики плюс network round-trip. Для высоконагруженных систем архитектура — Multi-Raft: множество независимых Raft-групп параллельно, каждая владеющая шардом keyspace.

  • CockroachDB: партиционирует keyspace в ~512 МБ “ranges”, одна Raft-группа на range.
  • TiKV: то же с ~100 МБ “regions”.
  • Kafka KRaft: одна Raft-группа на партицию metadata topic.

Heartbeat coalescing делает Multi-Raft жизнеспособным в масштабе: вместо 50 000 групп × 1 heartbeat/50 мс = 1М heartbeat/с, 5-нодовый кластер с 50 000 групп шлёт 10 физических пакетов на 50 мс (один на пару нод), каждый содержащий все heartbeat-ы групп в компактном битмапе. Это 200 пакетов/с вместо 1М.

Минимально жизнеспособный Raft dashboard

МетрикаПорог алертаКорневая причина при срабатывании
leader_changes_total в минуту>1/минFlapping leadership — проверь диск или heartbeat RTT
wal_fsync_duration_seconds p99>50 мсДиск слишком медленный — перейди на NVMe
commit_latency_seconds p99>100 мсДиск, сеть или follower lag
follower_lag_entries>1000Follower отстаёт — скоро может понадобиться snapshot
raft_term rate роста>2/минПовторные выборы — проверь сеть + pre-vote

Etcd поставляет etcd_server_leader_changes_seen_total, etcd_disk_wal_fsync_duration_seconds и etcd_network_peer_round_trip_time_seconds по умолчанию.

Три реальных production postmortem

GitHub октябрь 2018. Сетевой блип между датацентрами вызвал failover etcd. Misconfigured external sync писал в оба региона в краткое окно — Raft был корректен, оркестратор над ним — нет. Урок: Raft гарантирует консенсус внутри кластера; он не может защитить от misconfigured operator-слоя, пишущего мимо кластера.

Datadog 2023. TiKV-кластер испытывал повторные выборы лидера под высокой write-нагрузкой. Корневая причина: pre-vote был выключен в старой версии. Под write-давлением network jitter вызывал паразитные выборы, каждые из которых давали сотни миллисекунд недоступности. Включение pre-vote решило проблему. Урок: pre-vote — фича корректности, не nice-to-have.

Kubernetes etcd 2020. Админ удалил ноду из 3-нодового кластера без membership change API (вручную удалил data dir и переконфигурировал). Оставшиеся две ноды имели расходящиеся сохранённые конфигурации и циклически переключались между лидером и candidate. Фикс: остановить кластер, вручную поправить конфиги, рестарт. Урок: никогда не манипулируй Raft state вне собственного membership change path протокола.

Найди ошибку

Диагностируй лог Raft — что не так с follower D?

log
2026-05-13T15:42:08Z INFO  raft: leader=A term=12 commit=400123
2026-05-13T15:42:08Z INFO  raft: AppendEntries -> B success
2026-05-13T15:42:08Z INFO  raft: AppendEntries -> C success
2026-05-13T15:42:08Z INFO  raft: AppendEntries -> D failure (mismatch at idx=400100 term=12 vs follower idx=400100 term=11)
2026-05-13T15:42:09Z INFO  raft: AppendEntries -> D retry prevIdx=400050 (decremented)
2026-05-13T15:42:09Z INFO  raft: AppendEntries -> D failure (mismatch at idx=400050 term=12 vs follower idx=400050 term=10)
2026-05-13T15:42:10Z INFO  raft: AppendEntries -> D retry prevIdx=399000 (decremented)
2026-05-13T15:42:10Z INFO  raft: AppendEntries -> D failure (mismatch at idx=399000 term=12 vs follower idx=399000 term=8)
2026-05-13T15:42:11Z WARN  raft: D has diverged extensively; consider InstallSnapshot

Лидер постоянно уменьшает nextIndex для D. Каков диагноз и правильный операционный фикс?

Выбери лучший вариант

Стартап нуждается в strongly consistent KV store для service discovery. Выбери реализацию консенсуса, лучше балансирующую корректность, latency и операционное бремя.

Викторина

Почему наивная single-step смена конфига (добавление 3 нод одновременно без joint consensus) рискует split brain?

Вспомните перед уходом
  1. 01
    Объясни, почему joint consensus предотвращает риск split brain при membership change.
  2. 02
    CockroachDB-кластер запускает 50 000 Raft-групп. Почему это не коллапсирует под 1М heartbeat в секунду?
  3. 03
    Каков минимальный набор Raft-метрик для алертинга и что каждая диагностирует?
Итог

Безопасный membership change требует joint consensus — перехода через двойной кворум, предотвращающего окно, в котором два непересекающихся большинства могли бы выбирать конкурирующих лидеров. Leadership transfer через TimeoutNow снижает недоступность при rolling deploy с сотен миллисекунд до под 10 мс. Multi-Raft масштабирует throughput кластера через параллельные группы с coalesced heartbeat-ами. Минимально жизнеспособный Raft dashboard отслеживает пять метрик: смены лидера, WAL fsync latency, commit latency, follower lag и rate роста term. Каждый реальный production-инцидент с Raft восходит к одной из трёх корневых причин: membership change, обойдённый через joint consensus, выключенный pre-vote или WAL на медленном cloud-объёме. Фикси все три превентивно и покроешь 90% production-отказов Raft.

Связанные уроки
встречается в185
Продолжить восхождение ↑Raft: тест с выбором ответа
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources5
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05

Trademarks belong to their respective owners. Editorial reference only.