Kafka на собеседовании: System Design и типичные ошибки — Часть 9
Kafka часто появляется на собеседованиях не как отдельная технология, а как часть задачи по проектированию распределённой системы. То есть спрашивают вроде Kafka, а проверяют, умеете ли вы думать о порядке, сбоях и последствиях собственных решений.
Интервьюер может попросить спроектировать:
- систему заказов;
- обработку платежей;
- сервис уведомлений;
- поток логов;
- рекламную аналитику;
- видеохостинг;
- систему отслеживания действий пользователей.
В таких задачах недостаточно сказать:
Давайте поставим Kafka между сервисами.
Это звучит уверенно, но примерно как «давайте добавим микросервисы, и всё станет проще». Иногда станет. Но сначала нужно объяснить, почему.
Нужно объяснить:
- зачем Kafka здесь нужна;
- какие события будут публиковаться;
- как выбрать
TopicиKey; - какой порядок требуется;
- как масштабируются
Consumer; - что произойдёт при сбоях;
- допустимы ли повторные сообщения.
Исходный материал рассматривает Kafka именно как инструмент для подготовки к System Design интервью и предлагает выбирать между очередной и потоковой моделями в зависимости от характера задачи.
Вопрос 1. Что такое Kafka
Плохой ответ:
Kafka — это очередь сообщений.
Он не полностью неверный, но слишком упрощённый. На интервью такой ответ обычно не убивает диалог, но оставляет ощущение, что Kafka в вашей голове пока живёт в коробке с надписью «очереди».
Более точный ответ:
Apache Kafka — это распределённая платформа потоковой передачи событий, построенная вокруг партиционированного, реплицируемого и долговременно хранимого журнала. Producer записывают события в Topics, а Consumer читают их независимо, сохраняя собственную позицию через Offset.
После этого можно кратко добавить:
- Kafka поддерживает высокую пропускную способность;
- порядок гарантируется внутри
Partition; - сообщения не удаляются сразу после чтения;
- историю можно проигрывать повторно;
Consumerмасштабируются черезConsumer Groups.
Именно как распределённую платформу событий Kafka определяет исходная статья.
Вопрос 2. Чем Kafka отличается от обычной очереди
Главное различие — модель хранения и потребления.
В классической очереди:
Producer
|
v
Queue
|
v
Consumer
После успешной обработки сообщение обычно считается завершённым и удаляется либо становится недоступным другим Consumer.
В Kafka:
Producer
|
v
Append-Only Log
|
+--> Consumer Group A
|
+--> Consumer Group B
|
+--> Consumer Group C
Сообщение остаётся в журнале в соответствии с политикой Retention.
Каждая Consumer Group хранит собственную позицию и читает поток независимо.
Хорошая формулировка для интервью:
Очередь распределяет задачи между обработчиками, а Kafka хранит поток событий, который разные группы могут читать независимо. Поведение очереди в Kafka строится поверх Partition и Consumer Group.
Исходный материал отдельно сравнивает Kafka как Message Queue и как Stream.
Вопрос 3. Что такое Topic и Partition
Topic — это логическая категория сообщений.
Например:
orders
payments
users
Partition — физический упорядоченный журнал внутри Topic.
Topic: orders
Partition 0
Partition 1
Partition 2
Хорошее объяснение:
Topic отвечает за логическую организацию данных, а Partition — за масштабирование и параллелизм.
Один Topic может быть распределён по нескольким Broker, поскольку разные Partition размещаются на разных серверах.
Исходная статья формулирует это следующим образом: Topic организует данные, а Partition позволяет масштабировать их обработку.
Вопрос 4. Гарантирует ли Kafka порядок сообщений
Неправильный ответ:
Да, Kafka гарантирует порядок сообщений.
Правильный ответ:
Kafka гарантирует порядок только внутри одной Partition.
Представим Topic с тремя Partition:
Partition 0: A1 -> A2 -> A3
Partition 1: B1 -> B2 -> B3
Partition 2: C1 -> C2 -> C3
Порядок внутри каждой последовательности сохраняется.
Но Kafka не гарантирует общий порядок между A2, B2 и C2.
Если все события одного объекта должны обрабатываться последовательно, им назначают один Key.
Например:
Key = orderId
Тогда все события заказа попадут в одну Partition.
OrderCreated
PaymentCompleted
OrderShipped
Использование одного ключа для связанных сообщений описано в исходном материале как основной способ сохранить их порядок.
Вопрос 5. Как Producer выбирает Partition
Если Key указан, Producer вычисляет его хэш.
Упрощённо:
partition = hash(key) % partition_count
Одинаковый Key при неизменном количестве Partition обычно приводит в одну и ту же Partition.
Если Key отсутствует, Producer распределяет сообщения между Partition для балансировки нагрузки.
Хороший ответ должен включать компромисс:
Key обеспечивает порядок связанных событий, но неудачный Key может создать горячую Partition.
Например:
key = country
Если 80% сообщений приходят из одной страны, большая часть нагрузки окажется на одной Partition.
Исходная статья описывает как маршрутизацию по ключу, так и балансировку при его отсутствии.
Вопрос 6. Что такое Consumer Group
Consumer Group — это несколько Consumer, совместно обрабатывающих один Topic.
Partition 0 -> Consumer A
Partition 1 -> Consumer B
Partition 2 -> Consumer C
Каждая Partition назначается только одному Consumer внутри группы.
Это позволяет:
- обрабатывать сообщения параллельно;
- распределять нагрузку;
- избежать одновременного чтения одной
PartitionдвумяConsumerодной группы.
Но разные Consumer Group читают Topic независимо.
orders
|
+--> delivery-group
|
+--> analytics-group
|
+--> fraud-group
Один заказ увидят все три группы.
Именно Consumer Groups позволяют масштабировать обработку без двойного подсчёта событий внутри одной группы.
Вопрос 7. Что будет, если Consumer больше, чем Partition
Допустим:
Partitions: 3
Consumers: 5
Активно читать смогут только три Consumer.
Два остальных будут простаивать.
Причина:
Внутри одной Consumer Group одна Partition в конкретный момент назначается только одному Consumer.
Поэтому максимальный полезный параллелизм одной группы ограничивается количеством Partition.
Хороший ответ:
Добавление Consumer не поможет, если количество Consumer уже равно количеству Partition. Для дальнейшего масштабирования придётся увеличить число Partition или ускорить обработку.
Вопрос 8. Что такое Offset
Offset — последовательный номер записи внутри Partition.
Partition 0
Offset 0
Offset 1
Offset 2
Offset 3
Consumer использует Offset как закладку.
Consumer Group: analytics
Partition 0
Next Offset: 1504
Offset не является глобальным идентификатором сообщения.
Правильная уникальная позиция выглядит так:
Topic + Partition + Offset
Например:
orders / 2 / 1504
Offset позволяет Consumer продолжить работу после перезапуска и при необходимости повторно прочитать старые сообщения.
Вопрос 9. Почему Kafka такая быстрая
Хороший ответ должен состоять не из одной причины, а из нескольких.
Последовательная запись
Kafka дописывает сообщения в конец журнала.
Offset 100
Offset 101
Offset 102
New record -> Offset 103
Она не выполняет случайные изменения старых записей.
Page Cache
Kafka активно использует файловый кэш операционной системы.
Недавно записанные данные часто читаются непосредственно из RAM.
Batching
Producer и Consumer передают сообщения пачками, уменьшая количество сетевых операций.
Partitioning
Несколько Partition позволяют писать и читать данные параллельно.
Неизменяемость
Записанные Records не изменяются, что упрощает репликацию и уменьшает необходимость в блокировках.
Исходный материал выделяет последовательную запись, Page Cache, batching и параллелизм Partition как основные причины высокой пропускной способности.
Вопрос 10. Как Kafka обеспечивает отказоустойчивость
Каждая Partition может иметь несколько реплик.
Partition 0
Broker 1: Leader
Broker 2: Follower
Broker 3: Follower
Leader принимает операции чтения и записи.
Followers копируют журнал.
Если Leader выходит из строя, Controller выбирает нового Leader из актуальных реплик.
Хорошая формулировка:
Отказоустойчивость Kafka строится на репликации Partition, модели Leader-Follower и автоматическом выборе нового Leader из синхронизированных реплик.
Исходный материал описывает Leader, Followers, Controller и In-Sync Replicas как основу восстановления после отказа Broker.
Вопрос 11. Push или Pull
Kafka использует Pull-модель.
Consumer самостоятельно запрашивает данные у Broker.
Consumer -> fetch request -> Broker
Consumer <- records <- Broker
Преимущества:
Consumerконтролирует скорость чтения;- медленный
Consumerне перегружается принудительной отправкой; - данные можно получать крупными
Batch; Offsetможно сбросить и перечитать старые события.
Исходная статья называет управление нагрузкой, пакетное чтение и возможность перемотки основными преимуществами Pull-модели.
Вопрос 12. Может ли Kafka потерять сообщение
Правильный ответ:
Это зависит от конфигурации Producer, состояния реплик и момента подтверждения записи.
Типичные причины потери:
Producerне ждёт подтверждения;Leaderподтвердил запись до репликации;- несколько
Brokerвышли из строя; - неверно настроено число синхронных реплик;
- сообщение было подтверждено
Consumerдо завершения бизнес-операции; - срок
Retentionзакончился до того, какConsumerпрочитал данные.
На собеседовании важно разделять две ситуации.
Потеря внутри Kafka
Сообщение не сохранилось или исчезло при отказе кластера.
Пропуск на уровне Consumer
Сообщение есть в Kafka, но приложение сохранило Offset до успешной обработки.
Это разные классы проблем.
Вопрос 13. Может ли Kafka доставить сообщение дважды
Да.
Один из типичных сценариев:
1. Consumer получил сообщение
2. Выполнил операцию в базе
3. Упал до Commit Offset
4. После запуска получил сообщение повторно
Поэтому Consumer часто проектируют идемпотентным.
Хороший ответ:
При модели at-least-once дубликаты возможны, поэтому бизнес-операции должны безопасно переживать повторную обработку.
Например, можно использовать:
- уникальный
eventId; - уникальный ключ операции;
- таблицу обработанных сообщений;
- Inbox-паттерн;
- условное обновление состояния.
Гарантии at-most-once, at-least-once и exactly-once подробно не рассматриваются в исходной статье. Они добавлены здесь как практическое расширение интервью-гайда.
Вопрос 14. Что такое Consumer Lag
Consumer Lag — разница между последним Offset в Partition и текущей позицией Consumer Group.
Latest Offset: 100000
Consumer Offset: 97000
Lag: 3000
Lag показывает количество сообщений, которые группа ещё не обработала.
Сам по себе ненулевой lag не всегда означает проблему.
Важно смотреть:
- увеличивается ли он;
- как быстро
Consumerего сокращает; - равномерно ли он распределён по
Partition; - не закончится ли
Retentionраньше обработки.
Хорошая формулировка:
Consumer Lag — один из главных эксплуатационных показателей Kafka, но оценивать его нужно вместе со скоростью роста, временем обработки и требованиями бизнеса.
Вопрос 15. Что такое Rebalance
Rebalance — перераспределение Partition между Consumer одной группы.
Он происходит, например, когда:
- добавился новый
Consumer; Consumerзавершил работу;Consumerперестал отвечать;- изменилось количество
Partition; - изменился состав подписки.
До rebalance:
P0 -> Consumer A
P1 -> Consumer B
После падения Consumer B:
P0 -> Consumer A
P1 -> Consumer A
Проблема частых rebalance:
- обработка временно приостанавливается;
- растёт lag;
- могут появляться повторы;
- снижается общая производительность.
Вопрос 16. Как выбрать количество Partition
Универсального ответа нет.
Нужно учитывать:
- ожидаемую пропускную способность;
- скорость одного
Consumer; - необходимый параллелизм;
- требования к порядку;
- рост нагрузки;
- эксплуатационные ограничения кластера.
Пример рассуждения:
Ожидаемая нагрузка:
60 000 msg/s
Один Consumer:
10 000 msg/s
Минимальный параллелизм:
6
Следовательно, нужно не меньше шести Partition.
Затем добавляется запас на рост, например:
8 или 12 Partition
Но создавать сотни Partition без расчёта тоже не стоит: каждая из них требует метаданных, файлов, репликации и времени на rebalance.
Хороший ответ на интервью должен показать компромисс, а не назвать случайное число.
Вопрос 17. Когда Kafka использовать не стоит
Kafka не нужна автоматически в каждой микросервисной системе.
От неё лучше отказаться, если:
- приложение небольшое;
- поток сообщений низкий;
- нужна простая синхронная операция;
- система представляет собой обычный CRUD;
- команде нечем сопровождать Kafka-кластер;
- нет требований к повторному чтению истории;
- задачу проще решить базой данных или небольшой очередью.
Исходный материал прямо рекомендует избегать Kafka для маленьких приложений, низкой нагрузки, простых CRUD API и сценариев, где требуется сверхнизкая задержка RPC.
Вопрос 18. Kafka или RabbitMQ
Этот вопрос часто задают слишком широко.
Правильнее сравнивать инструменты через требования.
Kafka обычно выбирают, когда нужны
- высокая пропускная способность;
- долговременное хранение;
- повторное чтение истории;
- несколько независимых
Consumer Group; - Event Streaming;
- аналитические и событийные потоки.
Классический брокер очередей удобен, когда нужны
- маршрутизация отдельных задач;
- сложные схемы exchange и routing;
- очереди с коротким жизненным циклом;
- доставка команд конкретным обработчикам;
- относительно небольшая нагрузка;
- привычная модель ACK и удаления сообщений.
Хороший ответ:
Kafka не является универсальной заменой RabbitMQ. Kafka оптимизирована под долговременный распределённый журнал событий, а RabbitMQ — под маршрутизацию и доставку сообщений через классические очереди.
Это сравнение является практическим дополнением и не содержится в исходной статье.
System Design интернет-магазина
Рассмотрим типичную задачу.
Спроектируйте обработку заказов интернет-магазина.
Пользователь оформляет заказ.
После этого требуется:
- зарезервировать товар;
- начать платёж;
- отправить уведомление;
- обновить аналитику;
- проверить заказ на мошенничество.
Шаг 1. Публикуем событие
Order Service сохраняет заказ и создаёт:
OrderCreated
Событие публикуется в Topic:
commerce.orders.events
Шаг 2. Выбираем Key
Порядок нужен внутри одного заказа.
Следовательно:
Key = orderId
Все связанные события попадут в одну Partition:
OrderCreated
PaymentStarted
PaymentCompleted
OrderShipped
Шаг 3. Создаём независимые Consumer Group
commerce.orders.events
|
+--> inventory-group
|
+--> fraud-group
|
+--> notifications-group
|
+--> analytics-group
Каждая группа получает все события заказов, но обрабатывает их независимо.
Шаг 4. Масштабируем обработку
Допустим, Topic содержит 12 Partition.
Каждая Consumer Group может запустить до 12 активно работающих Consumer.
P0 -> Consumer 1
P1 -> Consumer 2
...
P11 -> Consumer 12
Шаг 5. Продумываем ошибки
Временные ошибки:
commerce.orders.retry.1m
commerce.orders.retry.10m
Необрабатываемые сообщения:
commerce.orders.dead-letter
Consumer должны быть идемпотентными, поскольку повторная доставка допустима.
Шаг 6. Продумываем надёжную публикацию
Есть сложная ситуация:
1. Order Service сохранил заказ в PostgreSQL
2. Не смог опубликовать OrderCreated в Kafka
Заказ существует, но другие сервисы о нём не узнали.
Обратный порядок тоже опасен:
1. Событие опубликовано
2. Транзакция базы откатилась
Consumer получили событие о несуществующем заказе.
Для решения часто используют Transactional Outbox:
PostgreSQL Transaction
+------------------+
| orders |
| outbox_events |
+------------------+
В одной транзакции сохраняются заказ и запись outbox.
Отдельный процесс публикует outbox-событие в Kafka.
Transactional Outbox не разбирается в исходной статье и приведён как практическое расширение System Design примера.
System Design обработки видео
Ещё одна популярная задача:
Пользователь загрузил видео. Нужно создать несколько форматов и превью.
Сервис публикации создаёт команду:
VideoUploaded
Topic:
media.video-processing
Consumer Group:
transcoding-workers
Kafka распределяет задачи между Worker.
P0 -> Worker A
P1 -> Worker B
P2 -> Worker C
Здесь Kafka работает ближе к модели очереди и используется как буфер между загрузкой и тяжёлой обработкой.
Аналогичный пример с транскодированием видео приводится в исходном материале.
System Design аналитики кликов
Задача:
Нужно в реальном времени считать клики по рекламе и выявлять мошенничество.
Каждый клик публикуется как событие:
{
"campaignId": "campaign-512",
"userId": "user-901",
"occurredAt": "2026-08-06T10:30:00Z"
}
Topic:
ads.clicks.events
Независимые группы:
ads.clicks.events
|
+--> realtime-aggregation
|
+--> fraud-detection
|
+--> data-warehouse
Здесь Kafka используется как поток событий, а не как очередь отдельных задач.
Исходная статья приводит рекламные клики как пример обработки непрерывного потока в реальном времени.
Ошибки кандидатов на System Design
«Добавим Kafka для масштабирования»
Это не объясняет, какую конкретно проблему она решает.
Нужно сказать:
- асинхронная обработка;
- развязка сервисов;
- поглощение всплесков;
- повторное чтение;
- один поток для нескольких систем.
«Kafka гарантирует доставку ровно один раз»
Слишком сильное утверждение.
Даже если Kafka предоставляет транзакционные механизмы, внешний эффект в базе, API или платёжной системе требует отдельного проектирования.
«Сделаем одну Partition, чтобы сохранить порядок»
Порядок действительно сохранится, но система потеряет масштабируемость.
Лучше определить, для какого объекта нужен порядок, и использовать его идентификатор как Key. Порядок «вообще для всего» звучит красиво, но часто заканчивается одной грустной Partition.
«Создадим тысячу Partition на будущее»
Это игнорирует стоимость метаданных, репликации, восстановления и rebalance.
Количество Partition должно следовать из нагрузки и требований к параллелизму.
«После чтения Kafka удаляет сообщение»
Kafka не связывает срок хранения с фактом чтения конкретным Consumer.
Удаление определяется Retention или compaction.
«Добавим ещё Consumer, и всё ускорится»
Только до тех пор, пока количество активных Consumer не сравняется с количеством Partition.
«Дубликатов не будет»
При сбоях между бизнес-операцией и commit offset повторная обработка возможна.
Нужна идемпотентность.
Как строить сильный ответ
Для любой Kafka-задачи можно использовать один порядок рассуждения.
1. Назовите проблему
Нужно развязать сервисы.
Нужно переживать пики нагрузки.
Нужно дать нескольким системам один поток событий.
2. Определите сообщение
Команда или событие?
Как оно называется?
Какие данные содержит?
3. Выберите Topic
commerce.orders.events
4. Выберите Key
orderId
5. Объясните порядок
Гарантируется для одного orderId.
6. Определите Partition
Количество основано на нагрузке и нужном параллелизме.
7. Опишите Consumer Group
Каждая функция получает отдельную группу.
8. Обсудите сбои
Репликация
Retries
Dead Letter Topic
Consumer Rebalance
9. Обсудите семантику обработки
At-least-once
Идемпотентный Consumer
10. Добавьте эксплуатацию
Consumer Lag
Under-replicated Partitions
Disk usage
Error rate
Такой ответ показывает понимание всей системы, а не знание отдельных терминов.
Краткий конспект Kafka
Kafka
Распределённая платформа потоковой передачи событий.
Broker
Сервер Kafka.
Topic
Логическая категория сообщений.
Partition
Упорядоченный append-only log внутри Topic.
Producer
Публикует Records.
Consumer
Читает Records.
Consumer Group
Набор Consumer, совместно обрабатывающих Partition.
Key
Определяет Partition и порядок связанных сообщений.
Offset
Позиция записи внутри Partition.
Leader
Основная реплика Partition.
Follower
Копирует данные Leader.
ISR
Набор актуальных реплик.
Retention
Определяет срок хранения сообщений.
Consumer Lag
Показывает отставание Consumer Group.
Rebalance
Перераспределяет Partition между Consumer группы.
Десять правил, которые стоит запомнить
- Kafka — это прежде всего распределённый журнал событий.
- Порядок гарантируется только внутри
Partition. - Один
Keyобычно означает однуPartition. Consumer Groupмасштабирует обработку.- Число активных
Consumerограничивается числомPartition. - Сообщение не удаляется сразу после чтения.
Consumerхранит позицию черезOffset.- Репликация защищает данные от отказа
Broker. - Повторная доставка возможна, поэтому нужна идемпотентность.
- Kafka стоит использовать только там, где её сложность оправдана.
Заключение
Kafka стала основой современных распределённых систем не потому, что она решает любую задачу. Она не заменяет базу данных, очередь, ETL, здравый смысл и нормальное проектирование.
Её сила — в нескольких хорошо сочетающихся свойствах:
- высокая пропускная способность;
- горизонтальное масштабирование;
- долговременное хранение событий;
- независимое чтение несколькими системами;
- возможность повторной обработки;
- устойчивость к отказу отдельных серверов.
Архитектурно Kafka остаётся достаточно простой:
Producer
|
v
Topic
|
v
Partition
|
v
Append-Only Log
|
v
Consumer
Но именно вокруг этой простой модели построены:
- репликация;
Consumer Groups;Offset;Retention;- потоковая обработка;
- Event-Driven архитектура.
Главная мысль всей статьи:
Kafka не должна быть магическим чёрным ящиком между сервисами.
Чтобы использовать её правильно, нужно понимать:
- как данные распределяются;
- где сохраняется порядок;
- что происходит при отказе;
- когда возникают дубликаты;
- как
Consumerмасштабируются; - кто отвечает за бизнес-консистентность.
Если эти принципы понятны, Kafka перестаёт выглядеть сложной системой и превращается в предсказуемый инженерный инструмент. Не простой, но честный: что спроектировали, то потом и сопровождаете.
Исходный материал завершает статью мыслью о Kafka как о «центральной нервной системе» современной архитектуры: платформе, которая одновременно служит надёжным буфером и потоком событий в реальном времени.