Що таке 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).