Условие
Что такое Apache Kafka и зачем он нужен в data-engineering? Объясните основные концепции: topic, partition, producer, consumer, consumer group. Чем Kafka отличается от обычной очереди типа RabbitMQ?
Решение
Подход
Kafka — распределённая платформа для event streaming: producer-ы пишут события в topics, consumer-ы читают и обрабатывают. Главное отличие от классических MQ — события сохраняются на диск с retention (часы, дни, недели), а не удаляются после прочтения. Это позволяет одновременным consumer-ам читать одни и те же события независимо, перечитывать историю и масштабировать обработку горизонтально.
Ключевые концепции.
- Topic — именованный лог событий. Похож на табличку в БД, только append-only.
- Partition — физический шард topic-а. Каждый partition — отдельный лог-файл. Параллелизм обработки = число партиций.
- Offset — порядковый номер записи внутри partition. Consumer хранит свой offset = «докуда дочитал».
- Producer — пишет события. Может выбирать ключ для определения partition (по умолчанию hash от ключа).
- Consumer group — группа consumer-ов, среди которых партиции делятся; одну партицию читает один consumer группы.
- Broker — нода Kafka-кластера; topic-партиции реплицированы между бродерами.
Гарантии доставки.
- At-most-once: можем потерять.
- At-least-once: дефолт, могут быть дубликаты — обработка должна быть идемпотентна.
- Exactly-once: возможно с transactions API и idempotent producer.
Чем отличается от RabbitMQ.
| Kafka | RabbitMQ | |
|---|---|---|
| Модель | Persistent log + pull | Queue + push |
| Удаление сообщений | По retention | После ack |
| Throughput | Десятки/сотни тысяч в сек | Тысячи |
| Latency | Миллисекунды | Микросекунды |
| Replay | Да | Нет |
| Сложность | Выше | Ниже |
Когда Kafka.
- Event sourcing.
- Streaming pipelines (ETL в стриме).
- Распределённое логирование.
- Бэкбон между микросервисами при больших объёмах.
Когда не Kafka.
- Маленький объём событий и низкая частота — overkill.
- Нужны сложные routing-rules и приоритеты — RabbitMQ удобнее.
# Producer (Python, confluent-kafka)
from confluent_kafka import Producer
p = Producer({"bootstrap.servers": "kafka:9092"})
p.produce("user_events", key="user-42", value=b'{"event":"signup"}')
p.flush()
# Consumer
from confluent_kafka import Consumer
c = Consumer({
"bootstrap.servers": "kafka:9092",
"group.id": "analytics",
"auto.offset.reset": "earliest",
})
c.subscribe(["user_events"])
while True:
msg = c.poll(1.0)
if msg and not msg.error():
process(msg.value())Подводные камни
- Число партиций определяет максимальный параллелизм. Поднять можно, опустить — нет. Закладывайте с запасом.
- Ключ определяет порядок. События с одним ключом всегда попадают в одну партицию (упорядочены). Без ключа — round-robin, порядок не гарантирован.
- Consumer lag — главная operations-метрика. Если consumer-ы не успевают, накопится backlog; добавляйте consumer-ы (но не больше, чем партиций).
- At-least-once дефолт — обработка должна быть идемпотентна.
- Reset offset = перечитать. Это мощно для повторной обработки после исправления багов пайплайна.
Эталонный ответ
Kafka — распределённый append-only лог событий с retention. Producer пишет в topic (разбит на партиции), consumer-группа читает параллельно по партициям. Главное отличие от MQ — события не удаляются после прочтения, можно реплеить и подключать новых consumer-ов независимо. Параллелизм определяется числом партиций; обработка — идемпотентна (at-least-once дефолт).