Консенсус и координация узлов
Консенсус - согласие узлов об одном значении при отказах: кто лидер, в каком порядке записи, кто в кластере. Собес проверяет, понимаешь ли ты, почему кворум - большинство, и зачем распределённому локу fencing token.
Стержень: большинство N/2+1 исключает две конкурирующие истории, поэтому чётное число узлов не даёт запаса, а лок без fencing небезопасен.
// Формулировки: «как работает Raft?», «зачем нечётное число узлов?», «что делает распределённый лок безопасным?».
Raft и большинство
Raft: лидер избирается голосами большинства в рамках терма (эпохи), запись это реплицированный лог, коммит наступает после подтверждения большинством. Понятная модель, которую и просят на собесе.
Кворум большинства (N/2+1) устроен так, что два непересекающихся большинства невозможны, поэтому расщеплённый кластер не примет две ветки истории.
// Прямое следствие: кластер из 2N узлов не лучше 2N−1. Четыре узла терпят один отказ, ровно как три, но платят за кворум большей латентностью. Отсюда нечётные 3 или 5.
- Raft
- консенсус: лидер + реплицированный лог с кворумным коммитом
- majority quorum
- большинство N/2+1, исключающее двойную историю
Размер кластера и FLP
Три или пять узлов координации - норма: 3 терпит 1 отказ, 5 терпит 2. Больше узлов - выше цена каждой записи, потому что кворум ждёт больше подтверждений; поэтому кластеры координации маленькие.
FLP-невозможность: в полностью асинхронной системе консенсус не гарантирован за конечное время. На практике живут таймаутами и рандомизацией - например, случайный election timeout в Raft разводит кандидатов, чтобы выборы сошлись.
// И кворум из узлов в одной стойке - псевдораспределённость: один сдохший свитч убивает всё «большинство» разом. Узлы координации разносят по отказовым доменам.
- FLP impossibility
- в асинхронной системе консенсус не гарантирован в срок
- election timeout
- рандомный таймаут выборов, разводящий кандидатов
Сервисы координации и локи
Координацию выносят в отдельный кворумный сервис - ZooKeeper, etcd, Consul: локи, выборы лидера, service discovery, метаданные. Свой Raft писать не надо, и это правильный дефолт.
Распределённый лок честен только с fencing token: обладатель лока мог зависнуть и «проснуться мёртвым» уже после того, как лок у него отобрали. Монотонный номер-токен отсекает его запоздалые записи.
// И граница применения: консенсус - дорогой примитив для маленьких критичных данных (конфиг, membership, лидерство), а не транспорт. Данные гоняют репликацией, координацию решают консенсусом; слать большие данные через etcd - ошибка.
- etcd / ZooKeeper
- кворумные сервисы координации и метаданных
- fencing token
- монотонный номер лока против зависших владельцев
Как отвечать: «Зачем консенсусу нечётное число узлов?»
Потому что решения принимаются большинством, N/2+1, и большинство должно быть единственным. Если кластер расщепится сетью на две части, только одна может собрать большинство и продолжить принимать записи - вторая заблокируется. Это и защищает от двух конкурирующих историй. Теперь арифметика: три узла терпят отказ одного (большинство - два, оно ещё собирается), пять терпят два. А четыре узла терпят тоже только один - при двух отказавших большинства из трёх не собрать, но при этом на каждую запись ждут подтверждения от большего числа узлов, то есть платят латентностью. Получается, чётное число даёт ту же отказоустойчивость, что предыдущее нечётное, но дороже. Поэтому берут 3 или 5. Больше пяти для координации редко нужно - цена кворума растёт быстрее пользы.
Почему это сильный ответ: связь большинства с невозможностью двух историй, точная арифметика отказоустойчивости (4 не лучше 3) и вывод про латентность - объяснено «почему», а не просто «берут нечётное».
На чём валят
- −Чётное число узлов кворума - 4 узла терпят столько же отказов, сколько 3.
- −Свой «распределённый лок» на Redis без fencing - зависший клиент пишет после потери лока.
- −Гонять большие данные через etcd/ZooKeeper - они для метаданных и координации.
- −Считать лидера вечным: любая логика обязана пережить смену лидера посреди операции.
- −Кворум из узлов в одной стойке - «распределённость» умирает с одним свитчем.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 11, остальные разбираются в тренажёре.
- Что такое split-brain в кластере и как fencing его предотвращает?A)Split-brain — это когда в кластере не остаётся лидера и запись встаётB)Fencing предотвращает split-brain, просто ускоряя выбор нового лидера после падения старогоC)Split-brain безопасен: два лидера автоматически синхронизируют свои записи между собой без потерьD)Два «лидера» разом; fencing отсекает старого, не даёт двойную запись
показать ответ и разбор
+D)Два «лидера» разом; fencing отсекает старого, не даёт двойную запись// разбор: Split-brain: при сетевом разделении или ложном срабатывании детектора отказа оба узла считают себя лидером и оба принимают записи — данные расходятся и повреждаются. Защита — fencing: гарантировать, что старый лидер не сможет писать. Приёмы: требовать кворум для лидерства (меньшинство само отказывается), fencing token (монотонный номер лидерства — хранилище отвергает запись со старым токеном), STONITH (принудительно вырубить старый узел). Опасность split-brain — почему выбор лидера строят на консенсусе с кворумом.
- Зачем распределённой системе распределённая блокировка (distributed lock) и в чём её главная опасность?A)Дать эксклюзивный доступ к ресурсу между узлами; опасность — держатель «умер»/завис, а лок остался или устарелB)Распределённый лок надёжен и дополнительных мер (fencing) не требуетC)Его главная опасность — замедление системы из-за ожидания освобождения ресурсаD)Распределённый лок обеспечивает эксклюзивность вообще без всяких таймаутов и токенов версии
показать ответ и разбор
+A)Дать эксклюзивный доступ к ресурсу между узлами; опасность — держатель «умер»/завис, а лок остался или устарел// разбор: Распределённый лок (через etcd/ZooKeeper/Redis) обеспечивает, что критическую секцию или ресурс держит только один узел из многих. Главная опасность — сбой держателя: если он завис (GC-пауза, сеть) или упал, лок надо освободить, но по таймауту его может подхватить другой, пока первый ещё «думает, что держит» — двойной доступ. Поэтому лок сопровождают fencing-токеном (ресурс отвергает операции с устаревшим номером лока) и коротким TTL с продлением. Без fencing распределённый лок не даёт настоящей гарантии эксклюзивности при сбоях.
- Что такое паттерн outbox и какую проблему двойной записи он решает?A)Outbox отправляет событие в брокер и пишет в БД строго одновременно двухфазным коммитом по сетиB)Паттерн outbox просто ретраит отправку события в брокер, пока она наконец не пройдёт успешноC)Outbox хранит события в памяти приложения и публикует их, теряя при перезапускеD)Событие и данные в одной транзакции, публикация из outbox отдельно
показать ответ и разбор
+D)Событие и данные в одной транзакции, публикация из outbox отдельно// разбор: Проблема dual-write: обновить БД и отправить событие в Kafka — две разные системы, и сбой между ними даёт рассинхрон (данные записаны, событие потеряно, или наоборот). Outbox: в той же транзакции, что и бизнес-данные, пишут событие в таблицу outbox — атомарно, всё или ничего. Отдельный процесс (poller или CDC по outbox) затем публикует эти события в брокер и помечает отправленными. Так гарантируется, что событие есть тогда и только тогда, когда есть данные — согласованность без распределённой транзакции.
- Что такое выбор лидера (leader election) в распределённой системе?A)Процесс, при котором каждый узел объявляет лидером себя, независимо от прочих узловB)Процесс, которым узлы согласованно выбирают один координирующий узел; при его падении выбирают новогоC)Ручная процедура, где администратор при каждом сбое сам назначает новый лидирующий узел, а остальные узлы принимают назначение без голосованияD)Выбор самого мощного по железу сервера, который затем не переизбирается при сбоях
показать ответ и разбор
+B)Процесс, которым узлы согласованно выбирают один координирующий узел; при его падении выбирают нового// разбор: Многие задачи требуют единственного координатора (кто применяет записи, раздаёт партиции, держит лок). Leader election — процедура, которой узлы через консенсус договариваются, кто лидер, и гарантируют, что он один. При падении лидера (пропали heartbeat'ы) запускается переизбрание из живых узлов. Строится на кворуме (лидер — тот, за кого проголосовало большинство), что заодно предотвращает двух лидеров сразу. Реализуется поверх Raft/ZooKeeper/etcd.
- Почему кворум большинства (majority quorum) при выборе лидера защищает от split-brain?A)Потому что при разделении сети обе стороны наберут большинство и договорятся между собойB)Потому что кворум большинства предотвращает сетевые разделения в кластереC)Большинство возможно лишь у одной стороны раздела — вторая, оставшись в меньшинстве, лидера не изберётD)Потому что меньшинство узлов автоматически становится лидером, разгружая тем самым перегруженное большинство
показать ответ и разбор
+C)Большинство возможно лишь у одной стороны раздела — вторая, оставшись в меньшинстве, лидера не изберёт// разбор: При сетевом разделении кластер распадается на группы. Правило «лидер — тот, кого поддержало большинство (> N/2) узлов» гарантирует, что большинство наберёт максимум одна сторона: другая, оказавшись в меньшинстве, не сможет избрать своего лидера и уходит в режим только-чтение/отказа. Так исключаются два пишущих лидера сразу (split-brain). Отсюда требование нечётного числа узлов и почему кластер из 2 узлов бесполезен для консенсуса — при разрыве большинства нет ни у кого.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.