📨 Раздел 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).

Связанные вопросы