📨 Розділ 15 · Питання #18

Що таке ISR (In-Sync Replicas)

Ключові властивості ISR:


🟢 Junior Level

30-секундна відповідь

ISR (In-Sync Replicas) — це динамічний список реплік партиції, які в поточний момент часу повністю синхронізовані з лідером і не відстають від нього за часом.

Ключові властивості ISR:

  • Лідер завжди входить до ISR: він є першоджерелом істини для партиції.
  • Кандидати в лідери: під час аварії поточного лідера кластер обирає нового лідера тільки з числа реплік, що входять до поточного ISR. Це гарантує нульову втрату підтверджених повідомлень.
  • Динамічний склад: якщо фолловер починає гальмувати або втрачає зв’язок з лідером, він виключається з ISR (Shrink). Щойно фолловер наздоганяє лідера, він повертається до ISR (Expand).

Наочна аналогія з життя

Уявіть раду директорів компанії:

  • Усі члени ради зобов’язані підписувати протоколи засідань протягом 30 хвилин.
  • Ті, хто підписав усі останні протоколи, входять до активного кворуму (ISR).
  • Якщо генеральний директор (Лідер) раптово йде з посади, тимчасово виконуючим обов’язки може бути призначений тільки директор з активного кворуму, оскільки він у курсі всіх останніх рішень. Запізнілий член ради до управління компанією не допускається.

Перевірка стану ISR через CLI

# Перегляд партицій та складу ISR для топіка payments
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic payments

Приклад виводу:

Topic: payments  Partition: 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
Topic: payments  Partition: 1  Leader: 2  Replicas: 2,3,1  Isr: 2,3

У другій партиції брокер 1 випав з ISR: брокери 2 та 3 синхронізовані, а брокер 1 перебуває в статусі відсталого (under-replicated).


🟡 Middle Level

Життєвий цикл ISR: Shrink та Expand

Складом ISR керує безпосередньо брокер-лідер партиції:

  1. Критерій синхронності (replica.lag.time.max.ms):
    • За замовчуванням дорівнює 30 000 мс (30 секунд).
    • Лідер відстежує час останнього успішного FetchRequest від кожного фолловера, який наздогнав LEO лідера.
    • Якщо фолловер не надсилає запитів або не наздоганяє LEO протягом 30 секунд, лідер ініціює процедуру ISR Shrink.
  2. ISR Shrink (Звуження):
    • Лідер виключає відсталого фолловера зі свого локального списку ISR.
    • Лідер надсилає запит контролеру кластера (AlterPartitionRequest у KRaft) для фіксації нового складу ISR у метаданих кластера.
  3. ISR Expand (Розширення):
    • Відсталий фолловер продовжує викачувати дані у фоні.
    • Коли його LEO зрівнюється з LEO лідера, лідер фіксує повернення фолловера і надсилає повідомлення контролеру про розширення ISR.
[ Лідер (LEO=100) ]
        │
        ├──(Fetch LEO=100 кожні 500мс)──► [ Брокер 2 ]  -> В ISR ✅
        │
        └──(Fetch LEO=40, затримка >30с)─► [ Брокер 3 ]  -> ISR Shrink ❌ (Випав)

Взаємодія ISR з acks=all та min.insync.replicas

  • acks = all означає, що продюсер чекає підтвердження від усіх поточних учасників ISR, а не від абсолютно всіх реплік топіка (replication.factor).
  • min.insync.replicas задає жорстку нижню межу розміру ISR для успішного запису:
Розмір ISR min.insync.replicas Результат для Producer (acks=all)
3 2 ✅ Запис прийнято та підтверджено всіма 3 репліками
2 2 ✅ Запис прийнято та підтверджено 2 репліками, що залишилися
1 2 ❌ Запис відхилено брокером: NotEnoughReplicasException

🔴 Senior Level

Внутрішній механізм Purgatory та підтвердження записів

Коли продюсер надсилає батч із acks = all:

  1. Лідер зберігає батч у локальний сегментний файл.
  2. Лідер поміщає запит у спеціальну внутрішню структуру очікування — DelayedProduce Purgatory (черга відкладених підтверджень).
  3. У міру того, як фоловери з ISR надсилають FetchRequest зі зсувами, що покривають батч, лічильник підтверджень інкрементується.
  4. Коли всі поточні члени ISR підтвердили запис:
    • Лідер просуває вперед High Watermark (HW).
    • Запит витягується з Purgatory, і продюсер отримує RecordMetadata зі зсувом.

Архітектурна еволюція: ZooKeeper vs KRaft

  • В епоху ZooKeeper (до Kafka 2.8/3.3):
    • Будь-яка зміна ISR вимагала від лідера прямого синхронного запису в ZNode /brokers/topics/<topic>/partitions/<partition>/state.
    • Під час масової деградації мережі (Flapping ISR) тисячі партицій одночасно починали спамити записами в ZooKeeper, призводячи до повного колапсу ZK-ансамблю та зависання всього кластера.
  • В епоху KRaft (Kafka 3.3+):
    • Лідер надсилає AlterPartitionRequest безпосередньо до активного Quorum Controller.
    • Контролер упаковує зміни в Raft-батчі в системному топіку @metadata, забезпечуючи мілісекундні затримки та масштабування до сотень тисяч партицій без зовнішніх залежностей.

4 Tricky Questions

1. Чи може брокер-лідер виключити сам себе зі списку ISR?

Відповідь:

  • Ні, лідер фізично не може виключити себе з ISR. Лідер партиції є безумовним та обов’язковим учасником ISR (ISR завжди містить ID лідера).
  • Якщо брокер-лідер стикається з апаратним блокуванням (наприклад, зависання диска при fsync), він не «виключає себе», а перестає відповідати на heartbeats контролеру кластера.
  • У цьому разі контролер фіксує збій брокера повністю та примусово призначає нового лідера з числа членів ISR, що залишилися. Старий брокер видаляється з метаданих.

2. Якщо RF = 3 і min.insync.replicas = 2, а розмір ISR впав до 1, чи можуть консьюмери продовжувати читати повідомлення?

Відповідь:

  • Так, можуть. Обмеження min.insync.replicas регулює виключно операції запису (ProduceRequest).
  • Операції читання (FetchRequest від консьюмерів) не блокуються. Консьюмери продовжують вичитувати всі повідомлення, що знаходяться в межах поточного зафіксованого High Watermark.
  • Партиція переходить у режим «Read-Only»: нові дані записати не можна, але вже підтверджені повідомлення залишаються повністю доступними для споживачів.

3. Чому часті коливання ISR (ISR Flapping) небезпечні для продуктивності кластера, і як з цим боротися?

Відповідь:

  • Якщо фолловер балансує на межі таймауту (наприклад, через Stop-The-World паузи GC на 28–32 секунди при ліміті у 30 секунд), виникає постійний цикл Shrink $\leftrightarrow$ Expand.
  • Кожна зміна ISR ініціює запис у контролер та розсилку широкомовного оновлення метаданих (MetadataUpdate) усім брокерам кластера.
  • Це викликає різке зростання мережевого керуючого трафіку, навантаження на CPU контролера та скидання внутрішніх кешів клієнтів.
  • Рішення: налаштувати моніторинг метрики kafka.server:type=ReplicaManager,name=IsrShrinksPerSec та усунути першопричину (тюнінг GC, збільшення replica.fetch.max.bytes або збільшення replica.lag.time.max.ms до 45–60 секунд).

4. Що відбувається з продюсером (acks = all), якщо під час очікування реплікації один із фолловерів зависає і виключається з ISR?

Відповідь:

  • Лідер не змушує продюсера чекати нескінченно.
  • У момент, коли лідер фіксує перевищення replica.lag.time.max.ms у завислого фолловера, він видаляє його зі списку ISR.
  • Щойно фолловер видалений, новий розмір ISR зменшується. Лідер перераховує кворум для запитів у Purgatory: тепер необхідний набір підтверджень включає тільки синхронних учасників, що залишилися.
  • Якщо залишковий ISR задовольняє min.insync.replicas, лідер негайно фіксує High Watermark і успішно відповідає продюсеру, не чекаючи таймауту request.timeout.ms.

🎯 Шпаргалка для інтерв’ю

Головне про ISR

  • Визначення: множина реплік, які повністю наздогнали лідера за часом (replica.lag.time.max.ms, типово 30с).
  • Лідер: завжди є частиною ISR.
  • Вибори лідера: тільки з ISR (при unclean.leader.election.enable = false).
  • Захист даних: acks = all + min.insync.replicas = 2 при RF = 3.
  • Under-Replicated Partitions: головна метрика здоров’я кластера; у нормі має суворо дорівнювати 0.

Таблиця метрик моніторингу ISR

| Метрика JMX | Критичність | Що означає при зростанні | | :— | :— | :— | | UnderReplicatedPartitions | 🔴 Critical | Кількість партицій, у яких розмір ISR менший за ReplicationFactor | | IsrShrinksPerSec | 🟡 Warning | Репліки випадають з ISR (проблеми мережі, I/O диска або довгі GC-паузи) | | IsrExpandsPerSec | 🟡 Warning | Репліки повертаються в ISR (часті цикли свідчать про нестабільність) | | UnderMinIsrPartitionCount | 🔴 Critical | Розмір ISR впав нижче min.insync.replicas — топік заблоковано на запис |

Червоні прапорці на співбесіді (Чого говорити не можна)

  • ❌ «До ISR входять тільки фоловери, а лідер стоїть окремо» — лідер обов’язково входить до ISR.
  • ❌ «Якщо розмір ISR менший за min.insync.replicas, консьюмери не можуть читати» — консьюмери читають дані до HW без жодних обмежень.
  • ❌ «Репліка випадає з ISR, якщо відстає на 10 000 повідомлень» — підрахунок за кількістю повідомлень давно видалено, поріг суворо за часом (replica.lag.time.max.ms).

Пов’язані запитання