Что такое репликация в Kafka
Количество копий задается параметром Replication Factor (RF) на уровне топика:
🟢 Junior Level
30-секундный ответ
Репликация в Kafka — это механизм копирования данных партиций на несколько независимых брокеров кластера для обеспечения высокой доступности (High Availability) и отказоустойчивости (Fault Tolerance).
Количество копий задается параметром Replication Factor (RF) на уровне топика:
- Leader (Лидер): ровно одна реплика партиции назначается лидером. Она принимает все входящие операции записи от продюсеров и (по умолчанию) обслуживает чтение консьюмерами.
- Followers (Последователи): остальные реплики пассивно вычитывают новые сообщения у лидера через внутренние Fetch-запросы, полностью дублируя его commit log на своих дисках.
- Если брокер с лидером выходит из строя, кластер автоматически выбирает нового лидера из числа актуальных фолловеров без остановки сервиса.
Наглядная аналогия из жизни
Представьте главного нотариуса и его помощников в разных зданиях:
- Лидер: главный нотариус, который лично заверяет все новые договоры (записи) в оригинале гроссбуха.
- Фолловеры: помощники в соседних офисах, которые непрерывно запрашивают у главного копии новых страниц и вклеивают их в свои дубликаты гроссбуха.
- Если здание главного нотариуса обесточено, один из помощников с самым полным журналом объявляется новым главным нотариусом.
Создание топика с репликацией
# Создание топика orders с 3 партициями и 3 репликами на кластере
kafka-topics.sh --bootstrap-server localhost:9092 --create \
--topic orders \
--partitions 3 \
--replication-factor 3 \
--config min.insync.replicas=2
🟡 Middle Level
Механика работы ISR (In-Sync Replicas)
Брокер-лидер отслеживает актуальность фолловеров с помощью списка ISR (In-Sync Replicas):
- Фолловер считается синхронизированным («in-sync»), если он регулярно отправляет
FetchRequestк лидеру и отставание по времени не превышаетreplica.lag.time.max.ms(по умолчанию 30 секунд). - Если фолловер завис (GC-пауза, сетевой сбой, диск I/O), лидер исключает его из ISR.
- Как только фолловер догоняет лидера, он автоматически возвращается в ISR.
Кластер с Replication Factor = 3:
[ Broker 1 (Leader) ] ───(Fetch)───► [ Broker 2 (Follower) ] -> Входит в ISR ✅
│
└────────────────(Fetch)───► [ Broker 3 (Follower) ] -> Lag > 30s -> Исключен из ISR ❌
Текущий ISR: [Broker 1, Broker 2]
Золотой треугольник надежности Kafka
Для 100% гарантии сохранности данных в продакшене три настройки должны работать строго вместе:
replication.factor = 3(на уровне топика) — 3 копии данных на разных физических серверах.min.insync.replicas = 2(на уровне топика или брокера) — минимальное число реплик в ISR, подтвердивших запись.acks = all(или-1) (на уровне продюсера) — продюсер ждет подтверждения от всех участников текущего ISR.
Properties producerProps = new Properties();
producerProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "broker1:9092,broker2:9092");
// Продюсер требует подтверждения от всего кворума ISR
producerProps.put(ProducerConfig.ACKS_CONFIG, "all");
// Включение идемпотентности гарантирует отсутствие дублей при ретраях репликации
producerProps.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
🔴 Senior Level
Внутренние маркеры репликации: LEO, HW и Leader Epoch
Репликация оперирует тремя фундаментальными смещениями:
0 1 2 3 4 5 6 7 8
┌───┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ m0│ m1 │ m2 │ m3 │ m4 │ m5 │ m6 │ m7 │ │
└───┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
▲ ▲
│ │
High Watermark (HW) Log End Offset (LEO)
- Log End Offset (LEO): смещение следующего сообщения, которое будет записано в лог конкретной реплики. У лидера и фолловеров свои локальные LEO.
- High Watermark (HW): максимальное смещение, которое успешно скопировано на все реплики из текущего ISR.
- Правило консьюмера: обычные консьюмеры имеют право читать данные только до High Watermark! Неподтвержденные репликами данные клиентам не отдаются.
- Leader Epoch (KIP-101): монотонно растущее число эпохи лидера, предотвращающее расхождение логов (Log Divergence) и фантомную потерю данных при каскадных сбоях лидеров.
Чтение с ближайшей реплики (Rack Awareness / KIP-392)
Исторически консьюмеры читали только с лидера. В мультизональных облаках (AWS Multi-AZ, GCP) это приводило к огромным расходам на межзональный трафик (Cross-AZ traffic). Начиная с Kafka 2.4 (KIP-392), консьюмер может читать напрямую с Follower-реплики, если они находятся в одном дата-центре:
# На брокере:
broker.rack=eu-west-1a
# На консьюмере:
client.rack=eu-west-1a
# Топик должен разрешать чтение с фолловеров
- Фолловер отдает консьюмеру данные только до своего локального High Watermark.
4 Tricky Questions
1. Почему связка replication.factor = 3 и acks = all абсолютно бесполезна для защиты от потери данных, если min.insync.replicas = 1?
Ответ:
- Продюсер с
acks = allждет подтверждения от всех реплик, находящихся в текущем ISR. - Если два брокера-фолловера упали или отстали из-за сети, брокер-лидер исключит их из ISR. В ISR останется ровно один участник — сам лидер (
ISR = [Broker 1]). - Так как
min.insync.replicas = 1, лидер посчитает, что условие минимального кворума выполнено, запишет сообщение локально и успешно ответит продюсеру: «Запись подтверждена!». - Если в следующую секунду у лидера сгорит жесткий диск, данные будут безвозвратно утеряны, несмотря на флаг
acks = all. - Вывод: Только при
min.insync.replicas = 2брокер отклонит запись ошибкойNotEnoughReplicasException, уведомив продюсера о невозможности гарантировать надежность.
2. Как внедрение Leader Epoch (KIP-101) решило проблему усечения логов (Log Truncation) и потери данных, возникавшую при использовании старого механизма High Watermark?
Ответ:
- В старых версиях Kafka фолловер обновлял свой High Watermark только со следующим Fetch-ответом от лидера.
- Если фолловер $F$ записал сообщение, но упал до обновления локального HW, то после перезагрузки он автоматически усекал свой лог до старого HW (считая несогласованные сообщения «мусором»).
- Если перед этим упал и лидер $L$, и брокер $F$ становился новым лидером, законно подтвержденные продюсеру сообщения навсегда исчезали из кластера.
- Leader Epoch ввел версионирование: при рестарте фолловер обращается к новому лидеру с запросом
LeaderEpochRequest(«Каков твой конец эпохи $N$?»), сравнивает фактические смещения эпох и обрезает лог только в том случае, если данные реально разошлись, предотвращая случайное удаление валидных записей.
3. Чем отличается исключение NotEnoughReplicasException от NotEnoughReplicasAfterAppendException?
Ответ:
NotEnoughReplicasException: Лидер проверил размер ISR до добавления сообщения в свой локальный лог. Видя, что размер ISR меньшеmin.insync.replicas, он мгновенно отвергает запрос продюсера. Лог лидера остается чистым.NotEnoughReplicasAfterAppendException: В момент прихода запроса ISR был в порядке. Лидер успел успешно записать сообщение в свой локальный log segment на диск. Но в процессе ожидания подтверждений от фолловеров фолловеры отвалились по таймауту, и ISR уменьшился ниже допустимого предела.- Для продюсера оба исключения являются поводом для ретрая, но при включенной идемпотентности дубликаты у лидера будут отфильтрованы по sequence number.
4. Что такое unclean.leader.election.enable и почему эта настройка по умолчанию строго false в современных версиях Kafka?
Ответ:
- Если лидер партиции падает, а все остальные реплики в данный момент не входят в ISR (отстали по времени или были недоступны):
- При
unclean.leader.election.enable = false: партиция становится полностью недоступной для чтения и записи. Кластер ждет оживления лидера или кого-то из ISR. Доступность (Availability) приносится в жертву целостности (Consistency). - При
unclean.leader.election.enable = true: брокер выбирает лидером несинхронизированную реплику (Out-of-Sync follower).
- При
- Опасность: несинхронизированный фолловер не содержит последних сотен или тысяч записей. Все эти записи безвозвратно теряются для консьюмеров, а оффсеты перезаписываются новыми данными, порождая повреждение данных во всей системе.
🎯 Шпаргалка для интервью
Главное о репликации
- Зачем нужна: отказоустойчивость и непрерывность бизнеса при падении серверов.
- Роли: ровно один Leader (read/write) и $N-1$ Followers (пассивные репликаторы лога).
- ISR (In-Sync Replicas): множество реплик, отставание которых от лидера не превышает
replica.lag.time.max.ms. - Продакшн-формула:
RF = 3,min.insync.replicas = 2,acks = all. - High Watermark (HW): граница, до которой данные видны консьюмерам.
Сравнительная таблица состояний репликации
| Сценарий | Доступность на запись | Доступность на чтение | Риск потери данных |
| :— | :— | :— | :— |
| ISR = 3, min.insync = 2 | ✅ Полная | ✅ Полная | ❌ Нулевой |
| ISR = 2, min.insync = 2 | ✅ Полная | ✅ Полная | ❌ Нулевой |
| ISR = 1, min.insync = 2 | ❌ Ошибка NotEnoughReplicas | ✅ Полная (по HW) | ❌ Нулевой |
| ISR = 1, min.insync = 1 | ✅ Полная | ✅ Полная | ⚠️ Критический риск при падении лидера |
Красные флаги на собеседовании (Чего говорить нельзя)
- ❌ «Каждая реплика партиции принимает параллельные записи от разных продюсеров» — только Лидер принимает запись!
- ❌ «Если поставить acks=all, данные никогда не потеряются даже при min.insync.replicas=1» — грубое непонимание работы ISR.
- ❌ «Консьюмер вычитывает самые свежие данные сразу, как только лидер положил их в память» — консьюмеры видят данные строго до High Watermark.