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