Apache Kafka на собеседовании Data Engineer

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Карьерник — 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 commitconsumer.commitSync() после успешной обработки. Безопаснее, но дороже по latency.

Rebalance — перераспределение партиций между консьюмерами при добавлении/падении одного из них. Во время ребаланса все консьюмеры в группе ничего не обрабатывают (стоп-зе-ворлд). На больших группах (50+) — болезненно. Mitigation:

  • Cooperative rebalancing (partition.assignment.strategy=CooperativeStickyAssignor) — инкрементальный ребаланс, не останавливает всех.
  • Static membership (group.instance.id) — при кратковременном падении консьюмер не вызывает ребаланс, его партиции ждут.
Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Семантика доставки

Три варианта, на собесе спросят все три:

At-most-once — сообщение придёт 0 или 1 раз, дублей нет, но возможна потеря. Получаем, если коммитим offset до обработки.

At-least-once — сообщение придёт 1 или больше раз, потерь нет, но возможны дубли. Получаем при коммите offset после обработки. Дефолт в большинстве кейсов: даунстрим должен быть идемпотентным.

Exactly-once — сообщение придёт ровно один раз. В Kafka достигается через:

  • Idempotent producer (нет дублей в партиции)
  • Transactional producer + read_committed consumer (атомарность 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. Даунстрим должен быть идемпотентным.

Связанные темы

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+ вопросами для собесов.