Что такое leader и follower реплики
Для каждой партиции топика в Kafka назначается группа реплик, распределенная по разным физическим брокерам. Внутри этой группы строго разделены две роли:
🟢 Junior Level
30-секундный ответ
Для каждой партиции топика в Kafka назначается группа реплик, распределенная по разным физическим брокерам. Внутри этой группы строго разделены две роли:
- Leader (Лидер): главная реплика партиции (всегда ровно одна). Она является единственной точкой входа для записи (
Produce) и стандартной точкой для чтения (Consume). Лидер управляет списком синхронных реплик (ISR) и вычисляет High Watermark. - Follower (Последователь): пассивные реплики-копии. Они не принимают команды на запись от клиентов. Их единственная задача — непрерывно запрашивать новые данные у лидера через внутренние Fetch-запросы, побайтово повторяя его журнал. В случае аварии лидера один из фолловеров мгновенно промоутится в нового лидера.
Наглядная аналогия из жизни
Представьте дирижера оркестра и музыкантов первой скрипки:
- Лидер (Дирижер): получает ноты новой симфонии от композитора (клиента-продюсера), задает темп и такт исполнения.
- Фолловеры (Скрипачи): непрерывно следят за движениями дирижера и в точности повторяют каждую ноту на своих инструментах.
- Если дирижеру стало плохо, первая скрипка немедленно берет дирижерскую палочку и продолжает концерт с той же ноты.
Просмотр ролей через консольные утилиты
# Просмотр распределения лидеров и реплик топика orders
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic orders
Пример вывода:
Topic: orders PartitionCount: 3 ReplicationFactor: 3
Topic: orders Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2,3
Topic: orders Partition: 1 Leader: 2 Replicas: 2,3,1 Isr: 2,3,1
Topic: orders Partition: 2 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
В данном выводе брокер 1 является лидером для партиции 0, а брокеры 2 и 3 — ее фолловерами.
🟡 Middle Level
Механика работы фолловеров: ReplicaFetcherThread
Фолловер взаимодействует с лидером точно так же, как обычный консьюмер:
- На каждом брокере работает пул потоков
ReplicaFetcherThread(их количество задается параметромnum.replica.fetchers). - Поток отправляет лидеру запрос
FetchRequest, указывая свой текущий локальныйLog End Offset (LEO). - Лидер считывает сообщения из своего лога (используя Linux PageCache и
sendfileбез копирования в user-space) и отдает их фолловеру. - Фолловер записывает батч в свой локальный segment file и отправляет следующий
FetchRequest, тем самым подтверждая успешную фиксацию предыдущей порции.
Внутренний цикл репликации
[ Продюсер ] ──(Produce)──► [ Брокер 1 (Leader) ]
▲
FetchRequest(LEO=105)
│
FetchResponse(105..110)
▼
[ Брокер 2 (Follower) ]
(ReplicaFetcherThread)
Предпочтительный лидер (Preferred Leader)
Список реплик в метаданных партиции упорядочен: Replicas: [2, 1, 3].
- Самый первый брокер в этом списке (
2) называется Preferred Leader (Предпочтительный лидер). - При создании топика Kafka равномерно раскидывает первых брокеров по кластеру для идеального распределения нагрузки.
- Если брокер 2 упал, лидером временно стал брокер 1. Но когда брокер 2 вернется в строй, механизм
auto.leader.rebalance.enable = trueавтоматически вернет лидерство брокеру 2.
🔴 Senior Level
Эволюция детекции отставания: почему отказались от replica.lag.max.messages
В ранних версиях Kafka (до 0.9) отставание фолловера определялось числом недополученных сообщений:
- Если фолловер отставал более чем на $N$ сообщений, он вылетал из ISR.
- Проблема: при внезапном всплеске трафика продюсер за 100 миллисекунд отправлял 10 000 сообщений. Абсолютно здоровые фолловеры не успевали выкачать их за доли секунды и массово вылетали из ISR, вызывая ложные алерты и деградацию кластера.
- Решение: параметр был полностью удален. Теперь используется исключительно временной порог
replica.lag.time.max.ms(дефолт 30 секунд). Если фолловер отправляет хотя бы один валидный Fetch-запрос каждые 30 секунд, он признается полноценным участником ISR, независимо от объема байт отставания.
Чтение с фолловеров: KIP-392 и Rack Awareness
По умолчанию клиенты общаются только с лидером. Однако при развертывании в облаках (AWS EC2 в разных Availability Zones) межзональный сетевой трафик стоит огромных денег.
С версии 2.4 добавлена возможность чтения с фолловеров:
- Брокер конфигурируется с указанием стойки/зоны:
broker.rack=us-east-1a. - Консьюмер настраивается аналогично:
client.rack=us-east-1a. - В кластере активируется селектор:
replica.selector.class=org.apache.kafka.common.replica.RackAwareReplicaSelector - Если в одной AZ с консьюмером есть Follower, находящийся в ISR, консьюмер читает данные напрямую с этого фолловера, экономя задержку и стоимость трафика. Фолловер отдает данные строго до своего High Watermark.
4 Tricky Questions
1. Как Kafka защищается от сценария Split-Brain («зомби-лидера»), когда старый лидер не знает, что контроллер уже выбрал нового?
Ответ:
- Если у лидера $L_1$ произошел сетевой разрыв с контроллером кластера (или долгая GC-пауза на 40 секунд), контроллер фиксирует тайм-аут и промоутит фолловера $L_2$ в нового лидера, инкрементируя номер эпохи:
Leader Epochстановится равным $N+1$. - Старый лидер $L_1$ оживает и все еще считает себя лидером (эпоха $N$).
- Когда продюсер или фолловер обращаются к $L_1$, либо когда сам $L_1$ пытается связаться с другими узлами, брокеры сверяют эпохи.
- Все запросы от узла со старой эпохой немедленно отклоняются фатальным исключением
FencedLeaderEpochException. Зомби-лидер принудительно сбрасывает статус, инвалидирует локальные метаданные и переключается в режим Follower.
2. Может ли консьюмер при чтении с Follower-реплики (KIP-392) столкнуться с «путешествием во времени» (чтением устаревших оффсетов)?
Ответ:
- Консьюмер читает данные порциями и хранит свой текущий оффсет.
- Фолловер отдает сообщения только до High Watermark, который гарантированно зафиксирован в ISR.
- Если консьюмер прочитал оффсет 500 у лидера, а затем переключился на фолловера, чей локальный High Watermark еще равен 490 (из-за небольшой задержки репликации), фолловер не отдаст старые или пустые данные. Он заблокирует Fetch-запрос клиента до тех пор, пока его собственный лог не догонит запрошенный оффсет (в пределах
fetch.max.wait.ms), либо отправит специальный ответ, вынуждающий клиента подождать. Нарушения монотонности оффсетов не происходит.
3. Почему при аварийном падении брокера-лидера партиция кратковременно недоступна, если фолловеры уже содержат все подтвержденные данные?
Ответ:
- Процесс failover не является абсолютно нулевым по времени:
- Падение лидера должно быть задетектировано контроллером кластера (по истечении тайм-аута сессии в ZK или heartbeat в KRaft, обычно 3–5 секунд).
- Контроллер должен записать новое состояние метаданных партиции в журнал метаданных (Raft quorum log).
- Контроллер рассылает обновление метаданных (
UpdateMetadataRequest) всем брокерам. - Клиенты (продюсеры и консьюмеры) при попытке обращения к старому лидеру получают ошибку
NotLeaderOrFollowerException, после чего инвалидируют свой кэш метаданных и запрашивают новые адреса у bootstrap-сервера.
- Весь цикл переключения занимает от сотен миллисекунд до нескольких секунд.
4. Что произойдет, если все фолловеры отстали и выпали из ISR, а затем упал и сам лидер?
Ответ:
- Кластер оказывается перед дилеммой теоремы CAP:
- Если
unclean.leader.election.enable = false(поведение по умолчанию): партиция полностью останавливает работу на чтение и запись. Она ждет, пока упавший лидер не перезагрузится и не восстановит свои данные. Целостность данных защищена, но доступность равна 0. - Если
unclean.leader.election.enable = true: контроллер выберет нового лидера из числа отставших фолловеров. Система продолжит работать, но все сообщения, которые лидер успел подтвердить продюсеру перед падением, будут безвозвратно удалены, а оффсеты перезаписаны.
- Если
🎯 Шпаргалка для интервью
Главное о Leader и Follower
- Leader: единственная реплика, принимающая запись. Координирует High Watermark и состав ISR.
- Follower: пассивная копия, вычитывающая данные через поток
ReplicaFetcherThread. - Preferred Leader: первая реплика в статическом списке, к которой кластер стремится вернуть лидерство для балансировки нагрузки.
- Fencing: механизм
Leader Epochисключает split-brain и запись в зомби-лидеров. - KIP-392: консьюмеры могут читать с локальных фолловеров в том же AZ/стойке (
client.rack).
Сравнение Leader vs Follower
| Параметр | Leader | Follower |
| :— | :— | :— |
| Прием сообщений от Producer | ✅ Да, единственный | ❌ Нет, отклоняет запросы |
| Выдача сообщений Consumer | ✅ По умолчанию | ⚠️ Только при настройке KIP-392 (Rack Aware) |
| Способ получения данных | Прямой append от клиентов | Запросы FetchRequest к лидеру |
| Управление ISR и HW | ✅ Да, рассчитывает и публикует | ❌ Нет, пассивно применяет |
Красные флаги на собеседовании (Чего говорить нельзя)
- ❌ «Фолловеры нужны для балансировки входящих записей от продюсеров» — продюсер пишет строго в лидера.
- ❌ «Фолловер исключается из ISR, если отстал хотя бы на 100 сообщений» — порог по числу сообщений давно удален, порог строго временной (
replica.lag.time.max.ms). - ❌ «Если упал лидер, кластер мгновенно теряет неподтвержденные данные» — данные подтверждаются только после репликации в ISR (High Watermark).