Kafka Flashcards
Kafka: что такое offset? Какими свойствами обладает? #Cian
- Оffset — это номер сообщения (целое число), который Kafka присваивает каждому сообщению внутри конкретной партиции.
o Он не пересекается с оффсетами из других партиций: каждая партиция имеет свой «счётчик».
o Возрастает строго последовательно: при записи каждого нового сообщения в партицию offset инкрементируется на 1. - Свойства:
1. Уникальность в пределах одной партиции: одно и то же число offset не используется повторно.
2. Упорядоченность: сообщения внутри партиции образуют линейный лог, отсортированный по offset.
3. Отслеживание прогресса: консьюмеры используют offset для понимания, «до какого места» они дочитали партицию. После успешной обработки консьюмер «коммитит» offset (сохраняет его в Kafka/внешнем сторе).
4. Контроль при сбоях: если консьюмер упал и перезапустился, он может узнать последний зафиксированный offset и начать чтение «с нужного места» (replay).
Вывод: Offset — ключевая часть механизма «расписания сообщений» в Kafka, позволяющая гарантировать «лог записи» и обеспечить идемпотентное чтение/повторное воспроизведение.
Кейс: Есть 1 топик с 3 партициями. Какое максимальное кол-во консьюмеров имеет смысл добавлять в consumer group, которая будет читать из этого топика? Почему? #Cian
- Максимальное количество активных консьюмеров в одной группе, которые действительно будут получать данные, равно количеству партиций (т. е. 3).
- Почему:
o Kafka распределяет партиции топика внутри consumer group таким образом, что каждую партицию читает ровно один консьюмер из группы.
o Если количество консьюмеров больше количества партиций (например, 4, 5 и т. д.), «лишние» консьюмеры простаивают (не получают сообщений). - Важно:
o Допускается иметь меньше консьюмеров, тогда одному консьюмеру достанется несколько партиций. Это нормально, если у нас недостаточно аппаратных ресурсов или нет необходимости в такой параллелизации.
o Но больше 3 в данном кейсе «смысла не имеет» с точки зрения параллельного чтения.
Вывод: Оптимально иметь не более 3 консьюмеров в группе при 3 партициях, чтобы каждый читал свою партицию.
- Зачем вообще нужен consumer group? Кейс: 3 consumer с 1 партицией в одной consumer group. Что произойдет, когда один consumer отвалится? #Cian
Consumer group — механизм, позволяющий:
1. Балансировать загрузку при чтении из топика: Kafka автоматически раздаёт партиции консьюмерам группы.
2. Обеспечить отказоустойчивость: если один консьюмер «падает» или «приходит», Kafka делает «rebalance», перераспределяя партиции по оставшимся (или новым) участникам группы.
- Кейс: 3 consumer + 1 партиция:
o Реально только 1 из них читает партицию (поскольку одна партиция назначается ровно одному консьюмеру). Остальные 2 «ждут» (простаивают).
o Если активный консьюмер «отваливается», rebalance перераспределит эту партицию к одному из «выживших» консьюмеров.
o Чтение продолжается, данные не теряются, так как offset хранится (commit) централизованно и при новом назначении можно продолжить с нужного места.
Вывод: Consumer group обеспечивает автоматическое переключение и распределение партиций между участниками группы, что делает систему более отказоустойчивой и масштабируемой.
Как пишутся сообщения в топик кафки? Какая там структура? #Cian
- Механика записи:
1. Producer отправляет сообщение в топик.
2. Если указан ключ (key), Kafka берёт хеш от ключа и решает, в какую партицию записать сообщение (или Round Robin, если ключ не задан).
3. Сообщение «добавляется» (append) в конец лога (файла) активного сегмента (группы запсией) партиции.
4. Присваивается offset — следующий по порядку в этой партиции.
5. Брокер может подтвердить (ACK) при репликации в нужное количество реплик (зависит от acks в настройках продьюсера). - Структура сообщения:
1. Key (опционально) — влияет на выбор партиции (также может использоваться потребителем для маршрутизации/сериализации).
2. Value (payload) — основные данные сообщения (JSON, Avro, Protobuf и т. д.).
3. Offset — порядковый номер в рамках партиции, автоматически присваивается брокером.
4. Timestamp — отметка времени (логическое или реальное время приёма).
5. Заголовки (headers) — могут содержать дополнительные метаданные. - Append-only log:
o Kafka хранит сообщения неизменяемо (immutable), лишь добавляет новые в «хвост» лога.
o Старые сообщения могут быть удалены по политике ретеншена (retention policy) через определённое время или когда общий размер превысит лимит.
Вывод: Запись в Kafka — это добавление сообщения в конец распределённого лога (партиции). Важны key, value, offset, timestamp.
Kafka vs RabbitMQ: Обсудили особенности и сравнительные характеристики этих систем очередей, их использование в разных сценариях и предпочтения. #🐺
Kafka и RabbitMQ — это оба брокеры сообщений, но они разные по философии, архитектуре и сценариям применения.
1. Основные отличия в идеологии:
- Kafka — это распределённый лог событий (“commit log”), где сообщения хранятся на диск надолго и читаются потребителями, как из файла. Kafka строилась для обработки большого потока данных с высокой скоростью и масштабируемостью.
- RabbitMQ — это классическая очередь сообщений (“message queue”). Она строилась для надежной передачи сообщений между сервисами с фокусом на гибкость маршрутизации, надёжную доставку и совместимость с разными протоколами.
2. Как работает Kafka:
- Сообщения пишутся в топики, а топик разбит на партиции.
- Сообщение в Kafka не исчезает после потребления: оно остаётся на диске, пока не наступит retention по времени или объему.
- Потребители сами запоминают, до какого смещения (offset) они дочитали. Это делает Kafka очень хорошей для повторного чтения событий (например, пересчёта данных).
- Kafka отлично масштабируется горизонтально за счёт партиционирования и репликации данных.
3. Как работает RabbitMQ:
- Сообщение передаётся через очередь. После получения и подтверждения (ack) потребителем оно удаляется из очереди.
- RabbitMQ поддерживает сложные паттерны маршрутизации через обменники (exchanges): direct, topic, fanout, headers.
- Есть поддержка различных стандартов (например, AMQP 0-9-1), что делает RabbitMQ гибким в интеграциях.
- RabbitMQ по умолчанию ориентирован на быстрые, но надежные передачи маленьких сообщений между системами.
4. Когда выбрать Kafka:
- Когда надо обрабатывать поток данных в реальном времени: лог событий, стриминг, аналитика, ETL-пайплайны.
- Когда важна производительность: Kafka легко держит сотни тысяч сообщений в секунду на кластере.
- Когда нужно хранение событий (например, чтобы воспроизвести состояние системы через event sourcing).
- Когда есть много потребителей и нужно, чтобы каждый обрабатывал события независимо.
Тонкость: Kafka не идеальна для передачи отдельных “важных” сообщений, например банковских транзакций. Она не гарантирует строгую немедленную доставку каждого сообщения как RabbitMQ (особенно при сбоях).
5. Когда выбрать RabbitMQ:
- Когда нужно надежно передавать команды от одного сервиса другому (например, “запусти платёж” или “удали пользователя”).
- Когда нужны гибкие схемы маршрутизации сообщений между системами.
- Когда важна поддержка транзакций на уровне очередей.
- Когда сообщения должны быть переданы ровно один раз (exactly-once delivery при правильно настроенных ack/retry механизмах).
Тонкость: RabbitMQ хуже масштабируется под огромные потоки данных без тщательной настройки, особенно в сценариях с большими очередями (там начинает страдать производительность).
6. По стабильности и отказоустойчивости:
- Kafka лучше справляется с потерями узлов и временной недоступностью (благодаря репликации и логам).
- RabbitMQ требует более аккуратной настройки кластеризации и управления связями между узлами, особенно при высоких нагрузках.
7. А что насчёт гарантии доставки сообщений?
- Kafka предлагает модели: at least once (минимум один раз, но может быть дубль) и exactly once (только начиная с новых версий Kafka + поддержка на уровне клиента и брокера).
- RabbitMQ изначально проектировался так, чтобы поддерживать “ack/retry” механизмы для надёжной доставки и позволяет точно один раз доставить сообщение при правильной настройке.
8. О накладных расходах:
- У Kafka довольно высокая стоимость инфраструктуры: нужны zookeeper (или KRaft режим), сервера с быстрыми дисками, хорошая сеть.
- RabbitMQ более лёгкий для старта, но при больших нагрузках может потребовать особой настройки (например, разбивки на кластеры с federation или sharding).
9. На что ещё могут спросить на собесе:
- У Kafka сообщения строго упорядочены внутри партиции, а в RabbitMQ порядок гарантируется внутри очереди, но сложные маршруты могут его ломать.
- У Kafka концепция “консьюмер групп” позволяет строить масштабируемую обработку событий параллельно.
- У RabbitMQ легко строить сложные очереди с разными политиками TTL (time-to-live), DLX (dead-letter exchanges) и др.
Итог:
- Kafka — для поточных данных, масштабируемости и устойчивого хранения событий.
- RabbitMQ — для гибкой маршрутизации, надёжной доставки команд и интеграции сервисов.
Хочешь, я ещё дополнительно подготовлю короткие формулировки типа “как ответить в двух предложениях на собесе”? Могу также заодно предложить примеры типовых вопросов по ним, которые часто задают на интервью. Нужно? 🚀
Архитектура кафки #Я
+Архитектура
- Кафку можно использовать как брокер сообщений
- Продьюсер создаёт сообщение и пишет в топик
- Топики разделены на партиции для масштабирования чтения
- Консьюмер подписан на топик и это новое сообщение читает
- Оффсет обозначает последнее обработанное сообщение в партиции
- Консьюмеры рекомендуется объединять в группы для автоматической балансировки нагрузки
- Основные компоненты Kafka
1.1. Producer (Производитель)Отправляет сообщения в топики (topics).
Может выбирать партицию, в которую будет записано сообщение (по ключу или случайно).
Поддерживает acknowledgements (acks), регулирующие подтверждение доставки.
1.2. Broker (Брокер)
Отвечает за хранение и доставку сообщений. Kafka-кластер состоит из множества брокеров, хранящих партиции топиков. Каждый брокер может быть лидером или репликой (фолловером) для определенных партиций.
1.3. Topic (Топик)
Логическое хранилище сообщений, разделенное на партиции. Новые сообщения добавляются в конец партиции и хранятся определенное время (по TTL).
1.4. Partition (Партиция)
Единица хранения сообщений в Kafka. Позволяет параллельно читать и писать данные, обеспечивая масштабируемость. У каждой партиции есть ведущий брокер (leader) и реплики (followers).
1.5. Consumer (Потребитель)
Читает данные из топиков, подписываясь на них. Может объединяться в группы потребителей (consumer groups). Каждый партиция назначается только одному потребителю в группе, обеспечивая балансировку нагрузки.
1.6. ZooKeeper
Используется для управления метаданными, лидерами партиций и координации брокеров. В новых версиях Kafka (с 3.0) можно использовать KRaft (Kafka Raft), убирая зависимость от ZooKeeper.
- Репликация и отказоустойчивостьФактор репликации (replication factor) — задает количество копий каждой партиции.
ISR (In-Sync Replicas) — список реплик, синхронизированных с лидером.
Если брокер-лидер выходит из строя, один из ISR-реплик становится новым лидером. - Потоковая обработка данных
Kafka поддерживает несколько моделей работы с данными:
Classic Pub/Sub — продюсеры публикуют, потребители читают. Kafka Streams API — встроенная библиотека для обработки потоков. Kafka Connect — интеграция с внешними системами (БД, Hadoop, ClickHouse и др.).
- Использование Kafka
Kafka применяется в:
Реальном времени ETL (ClickHouse, Spark, Flink). Логировании и мониторинге (Graylog, ELK, Prometheus). Обработке финансовых транзакций. IoT и телеметрии (автономные системы, датчики).
Kafka хороша для масштабируемых и отказоустойчивых систем, но требует продуманной архитектуры, особенно при выборе числа партиций и реплик.
Как хранится offset #Алексей
Кафка хранит оффсеты в разрезе [topic, partition, consumer_group] в техническом топике __consumer_offsets. Поменяй любую составляющую, получишь другой оффсет.
Что такое consumer group и как масштабировать чтения #Алексей
Нужна для увеличения устойчивости и балансировки нагрузки при масштабировании. Одну партицию читает строго один консьюмер из группы. Консьюмер может читать несколько партиций. Если одно сообщение нужно прочесть несколько раз из разных мест, создай несколько консьюмер групп.
Пусть p — партиция топика, c — консьюмер, g — группа консьюмеров:
1. Вначале p=[p1, p2], g=[c1]: с1 читает из [p1, p2]
2. Добавляем c2 в группу, g=[c1, c2]: p1->c1, p2->c2
3. Добавляем c3 в группу, g=[c1, c2, c3]: c3 простаивает
4. Убиваем c1, g=[c2, c3]: p1->c3, p2->c2
5. Добавляем 2 партиции, p=[p1, p2, p3, p4]: [p1, p3]->c3, [p2, p4]->c2
p.s. новая группа создаётся при конфигурации консьюмера просто указанием названия, которое отличается от прошлой группы; отдельных команд нет
Отличный и очень практичный вопрос, особенно с учётом реальных сценариев.
Отвечаю максимально подробно, включая нетривиальные детали и подводные камни.
Что такое consumer group в Kafka
Consumer group — это группа потребителей (consumers), которые совместно читают данные из топика (topic), разделённого на партиции (partitions).
Каждая партиция в каждый момент времени читается только одним consumer в рамках одной consumer group. Это очень важно.
- Если в топике 10 партиций и в группе 3 потребителя, то:
- Партиции будут распределены между ними. Например:
Consumer-1 -> Partition-0, Partition-1, Partition-2, Partition-3 Consumer-2 -> Partition-4, Partition-5, Partition-6 Consumer-3 -> Partition-7, Partition-8, Partition-9
- Если в топике 10 партиций, а в группе 10 потребителей, то каждый потребитель будет обрабатывать одну партицию.
- Если в группе 12 потребителей, а в топике 10 партиций, то два потребителя будут без работы. Это важный момент — число активных consumers не может превышать число партиций в топике. Остальные будут сидеть в режиме idle.
Зачем нужны группы:
- Горизонтальное масштабирование: каждый consumer может обрабатывать свой кусок данных.
- Fault tolerance: если consumer падает, Kafka перераспределяет партиции между оставшимися в группе.
-
Isolation между группами:
- Группа А и Группа Б читают данные независимо друг от друга. Это как отдельные подписчики на рассылку.
Как масштабировать чтение в Kafka
1️⃣ Увеличить число партиций топика
> Это основа масштабирования в Kafka.
- Количество параллельных потоков обработки = количество партиций.
- Чем больше партиций → тем больше consumers можно параллельно обрабатывать данные.
⚡️ Важное:
- Изменение числа партиций “на лету” может нарушить порядок сообщений.
- Сообщения с одинаковым ключом могут попасть в разные партиции после увеличения → порядок не гарантируется.
- Для этого используют Partitioning Strategies и явные ключи.
2️⃣ Увеличить число consumers в группе
- Дополнительные consumers позволят обрабатывать больше партиций параллельно.
- Но — см. выше — нельзя обрабатывать партиций больше, чем есть.
3️⃣ Параллелизм внутри consumer
- Даже если consumer обрабатывает одну партицию, можно внутри consumer:
- читать сообщения батчами (poll -> batch)
- пускать обработку в отдельные треды или async
- использовать пулы потоков (например, через concurrent.futures в Python или ExecutorService в Java)
Это часто упускают — масштабирование возможно даже на уровне одного consumer.
4️⃣ Использовать несколько consumer groups
- Каждая группа будет читать данные независимо.
- Полезно, если:
- нужно сделать несколько разных обработок (например, аналитика и триггеры).
- важно обеспечить независимость обработки (если одна группа тормозит, другая не пострадает).
Часто забываемые (но критичные) моменты
-
Число партиций определяет потолок параллелизма.
- Если топик создан с 3 партициями → максимум 3 consumers в группе будут активны.
- Остальные будут idle → это ловушка для неопытных.
-
Изменение количества партиций после запуска в проде — не всегда тривиально.
- При неправильном partitioning’е → возможно нарушение порядка.
-
Долгие операции в consumer могут заблокировать обработку всей партиции.
- Если consumer завис → вся партиция стоит.
- Поэтому параллелизм внутри consumer важен.
-
Авто-ребалансировка.
- При добавлении/удалении consumers → происходит ребалансировка → возможны короткие паузы в обработке.
Ключевая схема:
Topic (N партиций) | Consumer Group (M consumers) -> Каждая партиция -> Только 1 consumer в группе | Независимая обработка внутри consumer
Если коротко:
- партиции → определяют максимум параллелизма;
- consumers в группе → увеличивают скорость обработки;
- группы → обеспечивают независимость между разными задачами обработки;
- внутренний параллелизм → позволяет ускорить обработку даже одной партиции.
Хочешь — могу показать схему с редкими случаями типа:
- двух групп, одна из которых отстает (lag);
- ребалансировки в момент добавления нового consumer;
- борьбы с залипшими consumers.
Это будет максимально приближено к реальным продовым сценариям.
Дать такую схему? 👇
как интегрировать кафку с кликом? #Алексей
У клика есть kafka engine – возможность забирать данные из топика кафки без ETL инструментов. При этом, если кликхауз шардирован и реплицирован, то количество партиций в топике должно без остатка делиться на количество серверов CH, иначе возможен перекос данных из-за логики выбора партиции. Подробнее в докладе (рекомендую вообще целиком глянуть).