Apache Kafka на собеседовании Data Engineer
Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.
Содержание:
Почему Kafka спрашивают
Kafka — стандарт стриминга в РФ. Если в вакансии есть слово «event», «realtime» или «pipeline» — на собесе спросят про Kafka. Уровень: от «что такое топик» (junior) до «как разрулить ребаланс на 200 консюмерах» (middle+).
Главная боль без понимания Kafka — кандидат путает её с очередью (RabbitMQ) и предлагает «удалять сообщения после прочтения». В Kafka сообщения не удаляются по чтению — они лежат в топике до retention. Если на этом проколоться — собес заканчивается на десятой минуте.
Эта статья закрывает 90% базовых вопросов: устройство брокера, гарантии доставки, типичные грабли.
Топики, партиции, репликация
Топик — именованный поток событий. Не очередь — журнал (log). Сообщения упорядочены и доступны всем потребителям.
Партиция — единица параллелизма топика. Топик = N партиций. Внутри партиции порядок строгий, между партициями — нет. Пишут в партицию через хеш ключа: одинаковый ключ → одна партиция → строгий порядок для этого ключа.
topic: orders (3 партиции)
partition 0: msg1, msg2, msg5, msg8
partition 1: msg3, msg6
partition 2: msg4, msg7Репликация — копии партиции на других брокерах. replication.factor=3 — три копии: один лидер, два фолловера.
- Лидер — принимает запись/чтение
- Фолловер — догоняет лидера
- ISR (In-Sync Replicas) — фолловеры, которые не отстали больше, чем
replica.lag.time.max.ms
Если лидер падает — новый лидер выбирается из ISR. Если ISR пуст и unclean.leader.election.enable=false — партиция станет недоступна (consistency over availability). Если true — лидером станет отстающий фолловер, можно потерять данные.
На собесе типичный вопрос: «Сколько партиций нужно?» Правильный ответ — «зависит от throughput и параллелизма консьюмеров; число консьюмеров в группе ≤ числа партиций». Дефолт для среднего топика — 6–12.
Producer и acks
Producer пишет сообщение и ждёт подтверждения. Параметр acks определяет уровень гарантии:
| acks | Кто подтверждает | Гарантия | Latency |
|---|---|---|---|
0 |
Никто (fire-and-forget) | Можно потерять | Минимум |
1 |
Только лидер | Потеря при падении лидера до репликации | Среднее |
all (или -1) |
Все ISR | Не потеряем, пока ISR ≥ min.insync.replicas |
Максимум |
Для критичных данных (платежи, заказы) — всегда acks=all + min.insync.replicas=2 при replication.factor=3. Это значит: брокер примет запись, только когда минимум 2 реплики записали. Если осталась 1 ISR — продюсер получит ошибку, а не молча запишет в одну реплику.
Idempotent producer (enable.idempotence=true) — гарантия, что одно сообщение не попадёт в партицию дважды при ретраях. Producer добавляет sequence number, брокер дедуплицирует. С 3.0 включено по дефолту.
Transactional producer — атомарная запись в несколько партиций/топиков. Используется для exactly-once в Kafka Streams и connectors. Включается через transactional.id.
Consumer groups и offsets
Consumer group — набор консьюмеров, которые делят партиции топика. Каждая партиция отдаётся одному консьюмеру в группе.
topic orders (6 partitions), group A (3 consumers):
consumer-1 → p0, p1
consumer-2 → p2, p3
consumer-3 → p4, p5Если консьюмеров больше, чем партиций — лишние простаивают. Если меньше — кто-то берёт несколько.
Offset — позиция консьюмера в партиции. Хранится в служебном топике __consumer_offsets. Коммит offset:
- Auto-commit (
enable.auto.commit=true) — коммитит каждыеauto.commit.interval.ms(5 сек). Опасно: можно успеть закоммитить раньше, чем обработал → потеря. - Manual commit —
consumer.commitSync()после успешной обработки. Безопаснее, но дороже по latency.
Rebalance — перераспределение партиций между консьюмерами при добавлении/падении одного из них. Во время ребаланса все консьюмеры в группе ничего не обрабатывают (стоп-зе-ворлд). На больших группах (50+) — болезненно. Mitigation:
- Cooperative rebalancing (
partition.assignment.strategy=CooperativeStickyAssignor) — инкрементальный ребаланс, не останавливает всех. - Static membership (
group.instance.id) — при кратковременном падении консьюмер не вызывает ребаланс, его партиции ждут.
Семантика доставки
Три варианта, на собесе спросят все три:
At-most-once — сообщение придёт 0 или 1 раз, дублей нет, но возможна потеря. Получаем, если коммитим offset до обработки.
At-least-once — сообщение придёт 1 или больше раз, потерь нет, но возможны дубли. Получаем при коммите offset после обработки. Дефолт в большинстве кейсов: даунстрим должен быть идемпотентным.
Exactly-once — сообщение придёт ровно один раз. В Kafka достигается через:
- Idempotent producer (нет дублей в партиции)
- Transactional producer +
read_committedconsumer (атомарность multi-partition) - Kafka Streams
processing.guarantee=exactly_once_v2
Внешние системы (Postgres, ClickHouse) сами по себе не дают exactly-once. Чтобы записать в Postgres ровно раз — либо транзакция Kafka + 2PC (редко), либо идемпотентный INSERT (UPSERT по ключу).
Schema Registry и Avro
Schema Registry — сервис, хранящий схемы сообщений (Confluent или Karapace). Producer регистрирует схему, в сообщение пишет только её ID. Consumer достаёт схему по ID и десериализует.
Зачем: без Registry продюсер и консьюмер должны договориться о структуре. Если продюсер добавил поле — консьюмер падает. С Registry — поле эволюционирует по правилам совместимости.
Avro — бинарный формат с типизацией. Альтернативы: Protobuf, JSON Schema. Avro победил в Kafka-экосистеме за компактность и хорошую интеграцию.
Виды совместимости схем:
- Backward — новый консьюмер читает старые данные. Можно удалить поле или добавить с
default. - Forward — старый консьюмер читает новые данные. Можно добавлять поля, нельзя удалять.
- Full — обе стороны.
Дефолт в Confluent Registry — BACKWARD. На собесе спросят: «Можно ли добавить required-поле в Avro-схему?» Правильный ответ: «Нет, без default это сломает backward compatibility».
Частые ошибки
Путать Kafka с RabbitMQ. Kafka — журнал, сообщения не удаляются по чтению. RabbitMQ — очередь, удаляются после ack. Это разные модели.
Auto-commit на критичных данных. При падении консьюмера между коммитом и обработкой теряем сообщения. Для платежей — только manual commit после успешной обработки.
Один большой топик с 1 партицией. Без партиций нет параллелизма. Один консьюмер = one bottleneck. Минимум 3–6 партиций для среднего топика.
Полагаться на порядок между партициями. Порядок гарантирован только внутри партиции. Между партициями — нет. Если нужен глобальный порядок — 1 партиция (и ноль параллелизма).
Хранить большие сообщения в Kafka. Дефолтный лимит — 1 МБ. Большие файлы → S3, в Kafka — ссылка.
Считать exactly-once за пределами Kafka. Exactly-once в Kafka не означает exactly-once при записи в Postgres/ClickHouse. Даунстрим должен быть идемпотентным.
Связанные темы
- Подготовка к собесу Data Engineer
- Spark на собеседовании Data Engineer
- Airflow на собеседовании DE
- DWH ClickHouse на собесе DE
- SQL для Data Engineer: собеседование
FAQ
Чем Kafka отличается от RabbitMQ?
Kafka — распределённый журнал событий с длительным хранением и параллельным чтением через партиции. RabbitMQ — брокер очередей с маршрутизацией: сообщение удаляется после ack. Kafka выигрывает на throughput и replay, RabbitMQ — на сложной маршрутизации и low-latency RPC-стиле.
Что такое ISR и почему важно min.insync.replicas?
ISR — реплики, которые догнали лидера в пределах допуска. min.insync.replicas=2 при acks=all гарантирует, что запись подтверждена минимум двумя репликами. При min.insync.replicas=1 потеря лидера может означать потерю данных.
Как добиться exactly-once при записи из Kafka в Postgres?
Чистый exactly-once требует распределённой транзакции (2PC), что сложно. На практике делают идемпотентные UPSERT по бизнес-ключу: если consumer обработал сообщение дважды — UPSERT перезапишет ту же строку без дублей. Это at-least-once + idempotent sink, что эквивалентно exactly-once для большинства задач.
Сколько партиций задавать новому топику?
Стартовая эвристика: throughput сообщений в секунду / 10k = число партиций. Минимум 3 для отказоустойчивости, потолок ограничен числом параллельных консьюмеров. Лучше задать с запасом: уменьшить количество партиций нельзя без пересоздания топика.
Что такое rebalance и как его избежать?
Rebalance — перераспределение партиций при изменении состава consumer group. Полностью избежать нельзя, но можно сократить: cooperative rebalancing (инкрементально), static membership (group.instance.id), увеличение session.timeout.ms для коротких сетевых проблем.
Это официальная информация о вакансиях?
Нет. Статья основана на публичных источниках, документации Apache Kafka и опыте кандидатов. Конкретные требования зависят от компании, команды и уровня позиции.
Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.