Що таке 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 керує безпосередньо брокер-лідер партиції:
- Критерій синхронності (
replica.lag.time.max.ms):- За замовчуванням дорівнює 30 000 мс (30 секунд).
- Лідер відстежує час останнього успішного
FetchRequestвід кожного фолловера, який наздогнав LEO лідера. - Якщо фолловер не надсилає запитів або не наздоганяє LEO протягом 30 секунд, лідер ініціює процедуру ISR Shrink.
- ISR Shrink (Звуження):
- Лідер виключає відсталого фолловера зі свого локального списку ISR.
- Лідер надсилає запит контролеру кластера (
AlterPartitionRequestу KRaft) для фіксації нового складу ISR у метаданих кластера.
- 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:
- Лідер зберігає батч у локальний сегментний файл.
- Лідер поміщає запит у спеціальну внутрішню структуру очікування —
DelayedProduce Purgatory(черга відкладених підтверджень). - У міру того, як фоловери з ISR надсилають
FetchRequestзі зсувами, що покривають батч, лічильник підтверджень інкрементується. - Коли всі поточні члени 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-ансамблю та зависання всього кластера.
- Будь-яка зміна ISR вимагала від лідера прямого синхронного запису в ZNode
- В епоху 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).