Split brain — два узла одновременно считают себя лидером и принимают записи. Возникает при разделении сети или долгой паузе (GC, зависание VM): остальные решили, что лидер умер, и выбрали нового, а старый очнулся и продолжает писать. Итог — расходящиеся данные.
Большинство как защита. Если для любого решения нужно согласие более половины узлов, два решения не могут быть приняты разными группами — любые два большинства пересекаются хотя бы в одном узле. Отсюда размер кластера: из 3 узлов должны работать 2 (переживает 1 отказ), из 5 — 3 (2 отказа). 4 узла переживают тоже только 1 отказ — чётное число не помогает, а голосований больше.
Raft в общих чертах:
- время делится на сроки (terms) с номерами; в каждом сроке не более одного лидера;
- лидер рассылает heartbeat; узел, не получивший его за случайный таймаут, становится кандидатом, увеличивает term и просит голоса;
- узел голосует один раз за срок и только за кандидата, чей журнал не короче своего — так лидером не станет узел без подтверждённых записей;
- лидер добавляет записи в журнал и реплицирует; запись подтверждена, когда её сохранило большинство. Только тогда её применяют и отвечают клиенту;
- узел, увидевший больший term, сразу становится последователем — старый лидер, вернувшись, теряет полномочия.
Где используется: etcd (и значит Kubernetes), Consul, ZooKeeper (ZAB — похожий протокол), KRaft в Kafka, CockroachDB и YugabyteDB (Raft на каждый диапазон данных), Patroni через etcd.
Fencing. Даже с консенсусом старый лидер или держатель распределённой блокировки может не знать, что его сместили (пауза GC на 30 секунд, а аренда истекла). Защита — fencing token: при каждом назначении выдаётся монотонно растущий номер (term, версия блокировки), и хранилище отклоняет запросы с номером меньше уже виденного. Без этого распределённая блокировка на Redis с TTL небезопасна для корректности.
Цена консенсуса: каждая запись — оборот до большинства (поэтому узлы в разных зонах, а не континентах), лидер — узкое место записи, при потере большинства система перестаёт принимать записи (выбор C в CAP).