Как нам заставить кучу серверов вести себя как один? Есть три основных подхода.
Паттерн 1: Single-Leader (Синхронная репликация)
Самый простой в лоб:
- Запись идет только в Мастер.
- Мастер синхронно ждет ответа от всех Слейвов.
- Только потом отвечает клиенту.
Минус: Если один слейв в Австралии «моргнул» и отвалился от сети, зависнет вся система (потеря доступности).
Паттерн 2: Quorum (Кворум)
Используется в Dynamo-подобных базах (Cassandra, Riak, DynamoDB). В подходе выше мы сильно зависим от одного узла (мастера). Кворумный подход решает эту проблему: чаще всего в таком кластере все узлы равны (Leaderless архитектура), и мы отправляем запросы на чтение и запись сразу в несколько узлов.
Про leaderless архитектуру можешь прочесть в этом посте
Чтобы достичь строгой консистентности, нам не обязательно ждать все узлы. Достаточно математического большинства.
Формула строгой консистентности: W + R > N
- N — общее количество реплик, хранящих данные.
- W (Write Quorum) — количество узлов, которые должны подтвердить успешное сохранение, чтобы запись считалась успешной.
- R (Read Quorum) — количество узлов, которые нужно опросить при чтении.
Почему это работает?
Представь, что у нас кластер из 5 узлов (N=5). Если мы подтверждаем запись на 3 узлах (W=3) и читаем с 3 узлов (R=3), то по базовым законам математики эти два множества обязательно пересекутся минимум на одном узле.
Как система понимает, где новые данные?
При чтении координатор опрашивает R узлов и получает от них данные вместе с их версиями (таймстемпами или векторными часами, о которых мы говорили в прошлом видео).
Тот самый узел на пересечении гарантированно отдаст самую свежую версию данных. Система сравнивает таймстемпы, берет победившую версию (допустим, через Last Write Wins) и отдает клиенту. Остальные узлы со старыми данными заодно обновляются в фоне (это называется Read Repair).
Про то, как системы могут чинить себя сами (read repair) можешь прочесть в этом посте.
Конфигурации кворума под разные задачи:
- Сбалансированная (N=5, W=3, R=3): Классика. Система переживет падение любых двух узлов, сохранив строгую консистентность.
- Быстрая запись, тяжелое чтение (N=5, W=1, R=5): Запись моментальная (хватит одного узла), но чтение дорогое и медленное, так как нужно опросить весь кластер. И если хотя бы один узел упадет — чтение сломается.
- Быстрое чтение, тяжелая запись (N=5, W=5, R=1): Идеально для данных, которые редко меняются, но постоянно читаются (например, справочники).
Плюсы: Нет единой точки отказа (как в Master-Slave). Система отлично переживает падение части узлов (High Availability).
Минусы: Время ответа (latency) при записи или чтении всегда равно времени ответа самого медленного узла в кворуме. Если один сервер под нагрузкой тупит, будет тупить весь запрос клиента.
Паттерн 3: Алгоритмы Консенсуса (Raft / Paxos)
Данный подход часто используется в индустрии для критически важных метаданных (используется в etcd, Consul, ZooKeeper). Если первый паттерн (Single-Leader) был «глупым» и система ложилась при падении мастера, то алгоритмы консенсуса — это «умный» Single-Leader без единой точки отказа.
Как это работает
- Выбор лидера: узлы общаются между собой и выбирают лидера. Остальные становятся последователями. Если Лидер умирает, кластер это замечает по отсутствию пингов (heartbeats) и за миллисекунды проводит новые выборы.
- Журнал изменений: все изменения выстраиваются в строгую очередь в логе. Лидер — единственный, кто имеет право писать в этот журнал. Это дает нам ту самую гарантию порядка операций во времени (Linearizability), исключая любые конфликты.
- Кворумный коммит: когда приходит запись, лидер предлагает ее кластеру. Как только большинство узлов (кворум) ответило «я успешно записал это в свой лог», Лидер считает операцию закоммиченной и отвечает клиенту успехом.
То есть алгоритмы консенсуса объединяют плюсы первых двух подходов: строгий порядок от мастера (нет конфликтов при записи) и надежность кворума (можно пережить падение части машин).
Плюсы: консистентность, полная защита от split-brain (в кластере математически не может быть двух лидеров одновременно), автоматическое восстановление при сбоях.
Минусы: дорого по производительности из-за постоянных сетевых переписок для поддержания консенсуса.