Полное руководство

Apache Kafka: от нуля до продакшена

Что это за зверь, зачем нужен, как использовать и когда это избыточно. Разбираемся с распределённым брокером сообщений без воды.

📅 Актуально на 2025 ⏱ 25 мин чтения 💻 С примерами кода

🤔 Что такое Apache Kafka

Apache Kafka — это распределённая платформа потоковой передачи данных (distributed streaming platform). Проще говоря, это очень быстрый и надёжный почтовый сервис для ваших приложений.

Kafka изначально была разработана в LinkedIn в 2011 году для обработки триллионов сообщений в день. Позже передана Apache Software Foundation и стала open-source. Сегодня её используют Netflix, Uber, Spotify, Airbnb и более 80% компаний из Fortune 100.

📖 Почему "Kafka"?

Создатель Kafka, Jay Kreps, назвал систему в честь писателя Франца Кафки. По его словам, "Kafka — это система для оптимизации записи, а Кафка был писателем". Плюс имя звучало круто для open-source проекта.

Kafka в одном предложении

Kafka — это распределённый журнал сообщений, который позволяет приложениям публиковать, хранить и обрабатывать потоки записей в реальном времени.

📝
Publish/Subscribe
Одни приложения отправляют сообщения, другие — подписываются и получают. Отправитель не знает, кто прочитает.
💾
Хранение
В отличие от обычных очередей, Kafka хранит сообщения на диске. Можно перечитать данные за прошлую неделю.
Потоковая обработка
Обработка данных в реальном времени, по мере поступления. Не batch, а stream.
🔄
Масштабируемость
Горизонтальное масштабирование — добавляй серверы, увеличивай пропускную способность.

🎯 Зачем нужна Kafka

Представьте: у вас интернет-магазин. Пользователь делает заказ. Что происходит?

Без Kafka (синхронный подход)

Сервис заказов напрямую вызывает: сервис оплаты → сервис склада → сервис доставки → сервис уведомлений → сервис аналитики. Если один упал — всё встало.

С Kafka (асинхронный подход)

Сервис заказов публикует событие "Создан заказ" в Kafka. Все остальные сервисы подписаны и обрабатывают независимо. Упал склад? Заказ всё равно принят, склад обработает, когда встанет.

Архитектура с Kafka
🛒
Order Service
Producer
📨
Apache Kafka
Topic: orders
💳 Payment
📦 Warehouse
📧 Notifications

Главные проблемы, которые решает Kafka

🔗
Развязывание сервисов
Сервисы не знают друг о друге напрямую. Меньше зависимостей — проще менять и масштабировать.
🛡️
Надёжность
Сообщения не теряются даже при падении consumer'ов. Kafka хранит их, пока не обработают.
📈
Пиковые нагрузки
Чёрная пятница? Kafka буферизует миллионы заказов, consumer'ы обрабатывают в своём темпе.
🔄
Replay событий
Нашли баг в обработке? Перечитайте события заново. Данные никуда не делись.

🧱 Ключевые концепции

Чтобы работать с Kafka, нужно понимать несколько базовых терминов. Без паники — их немного.

📌 Topic (Топик)

Топик — это категория или "канал", куда публикуются сообщения. Как папка для писем. Например: orders, user-events, payments.

📨 Message (Сообщение)

Сообщение — единица данных в Kafka. Состоит из:

  • Key — ключ (опционально), определяет партицию
  • Value — само содержимое (JSON, Avro, bytes)
  • Timestamp — время создания
  • Headers — метаданные

📦 Partition (Партиция)

Партиция — это часть топика. Топик разбивается на партиции для параллельной обработки. Сообщения в одной партиции упорядочены.

💡 Аналогия

Топик — это журнал заказов. Партиции — это страницы журнала. Заказы с одним customer_id всегда попадают на одну страницу (партицию), поэтому их порядок сохраняется.

🏭 Producer (Продюсер)

Producer — приложение, которое отправляет сообщения в Kafka. Знает только о топике, куда писать.

👥 Consumer (Консьюмер)

Consumer — приложение, которое читает сообщения из Kafka. Подписывается на топик и обрабатывает события.

👥 Consumer Group

Consumer Group — группа consumer'ов, которые вместе обрабатывают топик. Kafka распределяет партиции между ними. Если один упал — его партиции достанутся другим.

📍 Offset (Смещение)

Offset — позиция сообщения в партиции. Это как номер страницы в книге. Consumer помнит свой offset и продолжает с него после перезапуска.

🖥️ Broker

Broker — сервер Kafka. Кластер обычно состоит из нескольких брокеров для отказоустойчивости.

Визуализация kafka-structure.txt
Kafka Cluster
├── Broker 1
├── Broker 2  
└── Broker 3

Topic: orders (3 partitions, replication factor: 2)
├── Partition 0: [msg0, msg3, msg6, msg9...]  → Broker 1 (leader), Broker 2 (replica)
├── Partition 1: [msg1, msg4, msg7, msg10...] → Broker 2 (leader), Broker 3 (replica)
└── Partition 2: [msg2, msg5, msg8, msg11...] → Broker 3 (leader), Broker 1 (replica)

Consumer Group: order-processors
├── Consumer A → читает Partition 0
├── Consumer B → читает Partition 1
└── Consumer C → читает Partition 2

🏗️ Архитектура Kafka

Kafka спроектирована для высокой пропускной способности, низкой задержки и отказоустойчивости. Вот как это достигается:

Распределённый лог

В основе Kafka — append-only log. Сообщения только добавляются в конец, никогда не изменяются. Это позволяет:

  • Очень быстро писать (sequential I/O)
  • Читать с любой позиции (offset)
  • Хранить данные неделями/месяцами

Репликация

Каждая партиция имеет leader и несколько replicas. Все записи идут в leader, replicas синхронизируются. Если leader умирает — одна из replica становится новым leader.

ZooKeeper vs KRaft

Раньше Kafka использовала ZooKeeper для координации кластера (выбор leader, хранение метаданных). С версии 3.0 появился режим KRaft — встроенный консенсус без внешних зависимостей.

⚠️ KRaft в 2025

Для новых проектов рекомендуется использовать KRaft (без ZooKeeper). Это проще в настройке и поддержке. ZooKeeper будет deprecated в будущих версиях.

Гарантии доставки

Режим Описание Когда использовать
At-most-once Сообщение может потеряться, но не дублируется Логи, метрики (потеря не критична)
At-least-once Сообщение точно доставлено, возможны дубли Большинство случаев (default)
Exactly-once Сообщение доставлено ровно один раз Финансы, критичные операции

🚀 Быстрый старт

Самый простой способ запустить Kafka локально — использовать Docker. Никаких танцев с бубном.

1
Создайте docker-compose.yml
Этот конфиг поднимет Kafka в режиме KRaft (без ZooKeeper):
YAML docker-compose.yml
version: '3.8'

services:
kafka:
image: confluentinc/cp-kafka:7.5.0
hostname: kafka
container_name: kafka
ports:
  - "9092:9092"
environment:
  KAFKA_NODE_ID: 1
  KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT'
  KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://localhost:9092'
  KAFKA_PROCESS_ROLES: 'broker,controller'
  KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka:29093'
  KAFKA_LISTENERS: 'PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:29093'
  KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
  KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
  CLUSTER_ID: 'MkU3OEVBNTcwNTJENDM2Qk'

kafka-ui:
image: provectuslabs/kafka-ui:latest
container_name: kafka-ui
ports:
  - "8080:8080"
environment:
  KAFKA_CLUSTERS_0_NAME: local
  KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
depends_on:
  - kafka
2
Запустите контейнеры
Terminal
$ docker-compose up -d
Creating network "kafka_default" with the default driver
Creating kafka ... done
Creating kafka-ui ... done
 
$ docker-compose ps
NAME STATUS PORTS
kafka Up 0.0.0.0:9092->9092/tcp
kafka-ui Up 0.0.0.0:8080->8080/tcp
3
Откройте Kafka UI
Перейдите на http://localhost:8080 — там можно создавать топики, просматривать сообщения и мониторить кластер.
✅ Готово!

Kafka работает на localhost:9092. Теперь можно подключаться из приложений.

💻 Примеры кода

Рассмотрим, как работать с Kafka на разных языках. Начнём с самых популярных.

Python (kafka-python)

Python producer.py
from kafka import KafkaProducer
import json

# Создаём producer
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8')
)

# Отправляем сообщение
order = {
'order_id': 12345,
'user_id': 67890,
'product': 'iPhone 15',
'amount': 999.99
}

producer.send('orders', value=order)
producer.flush()  # Дожидаемся отправки

print('Order sent!')
Python consumer.py
from kafka import KafkaConsumer
import json

# Создаём consumer
consumer = KafkaConsumer(
'orders',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='earliest',  # Читать с начала, если нет сохранённого offset
group_id='order-processors',
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)

# Читаем сообщения
for message in consumer:
order = message.value
print(f"Received order: {order['order_id']} - {order['product']}")

# Обработка заказа...
process_order(order)

Node.js (kafkajs)

JavaScript producer.js
const { Kafka} = require('kafkajs');

const kafka = new Kafka({
    clientId: 'order-service',
    brokers: ['localhost:9092']
});

const producer = kafka.producer();

async function sendOrder() {
    await producer.connect();

    const order = {
        order_id: 12345,
        user_id: 67890,
        product: 'MacBook Pro',
        amount: 2499.99
    };

    await producer.send({
        topic: 'orders',
        messages: [
            { value: JSON.stringify(order) }
        ]
    });

    console.log('Order sent!');
    await producer.disconnect();
}

sendOrder();
JavaScript consumer.js
const { Kafka } = require('kafkajs');

const kafka = new Kafka({
    clientId: 'order-processor',
    brokers: ['localhost:9092']
});

const consumer = kafka.consumer({ groupId: 'order-processors' });

async function consumeOrders() {
    await consumer.connect();
    await consumer.subscribe({ topic: 'orders', fromBeginning: true });

    await consumer.run({
        eachMessage: async ({ topic, partition, message }) => {
            const order = JSON.parse(message.value.toString());
            console.log(`Received: ${order.order_id} - ${order.product}`);

            // Обработка заказа...
            await processOrder(order);
        }
    });
}

consumeOrders();

Java (Spring Kafka)

Java OrderProducer.java
@Service
public class OrderProducer {

    private final KafkaTemplate<String, Order> kafkaTemplate;

    public OrderProducer(KafkaTemplate<String, Order> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    public void sendOrder(Order order) {
        kafkaTemplate.send("orders", order.getOrderId(), order);
        log.info("Order sent: {}", order.getOrderId());
    }
}
Java OrderConsumer.java
@Service
public class OrderConsumer {

    @KafkaListener(topics = "orders", groupId = "order-processors")
    public void consume(Order order) {
        log.info("Received order: {} - {}", order.getOrderId(), order.getProduct());

        // Обработка заказа
        orderService.process(order);
    }
}
📦 Установка зависимостей

Python: pip install kafka-python
Node.js: npm install kafkajs
Java: Spring Boot Starter: spring-kafka

Когда использовать Kafka

Kafka — мощный инструмент, но не серебряная пуля. Вот сценарии, где она реально нужна:

Опционально

📝 Audit Log / Event Sourcing

Хранение всех событий как источника правды. Kafka хранит данные долго, можно перестроить состояние системы.

Опционально

🛡️ Буфер перед медленными системами

API принимает запросы быстро, складывает в Kafka. Медленный бэкенд обрабатывает в своём темпе.

Шкала масштаба: когда Kafka оправдана

🏠 Маленький проект
< 100 msg/sec, 1-3 сервиса
❌ Избыточно
Используйте Redis Pub/Sub, RabbitMQ или просто HTTP. Kafka — это overhead в инфраструктуре и знаниях.
🏢 Средний проект
100-10K msg/sec, 5-20 сервисов
🤔 Зависит от задачи
Если нужна надёжность, replay событий, долгое хранение — Kafka. Если просто очередь задач — RabbitMQ проще.
🏭 Большой проект
> 10K msg/sec, 20+ сервисов
✅ Рекомендуется
Kafka создана для этого. Масштабируется горизонтально, обеспечивает надёжность и производительность.
🌍 Enterprise
Миллионы msg/sec, сотни сервисов
✅ Must have
На этом уровне альтернатив практически нет. LinkedIn, Netflix, Uber — все используют Kafka.

🚫 Когда НЕ использовать Kafka

Важно понимать, что Kafka — это не универсальное решение. Вот случаи, когда она избыточна или не подходит:

Избыточно

🚫 Простая очередь задач

Отправить email, обработать картинку, запустить отчёт. Для этого есть RabbitMQ, Redis Queue, Celery. Проще и дешевле.

Избыточно

🚫 Запрос-ответ (RPC)

Kafka — это pub/sub, не request/response. Для синхронного общения используйте gRPC, REST, или RabbitMQ с reply-to.

Избыточно

🚫 Маленькая команда, стартап

Kafka требует экспертизы: настройка, мониторинг, дебаг. Если у вас 2-3 разработчика — это отвлечёт от продукта.

Избыточно

🚫 Монолитное приложение

Если у вас один сервис — зачем обмен сообщениями? Kafka нужна для коммуникации между сервисами.

Не подходит

🚫 База данных

Kafka — не замена PostgreSQL. Нет индексов, нет сложных запросов, нет UPDATE/DELETE. Это лог, не хранилище.

Не подходит

🚫 Гарантированный порядок по всем данным

Порядок гарантирован только внутри партиции. Глобальный порядок = одна партиция = нет масштабирования.

🚨 Типичная ошибка

"Мы используем Kafka для отправки email" — это антипаттерн. Для таких задач Redis + Celery или RabbitMQ работают лучше, проще в настройке и не требуют команды DevOps для поддержки.

Честный чек-лист: нужна ли вам Kafka?

Checklist do-i-need-kafka.md
Отвечайте честно:

Обязательные условия (нужны ВСЕ):
[ ] У вас микросервисная архитектура (5+ сервисов)
[ ] Сервисам нужно обмениваться событиями асинхронно
[ ] Вы готовы поддерживать Kafka (или платить за managed)

Дополнительные факторы (достаточно 2-3):
[ ] Нагрузка > 1000 сообщений в секунду
[ ] Нужно хранить события для replay/audit
[ ] Несколько consumer'ов читают одни данные
[ ] Критично не потерять сообщения
[ ] Нужна потоковая обработка (Kafka Streams)

Результат:
- Все обязательные + 2 дополнительных → Kafka подходит
- Не все обязательные → Рассмотрите альтернативы
- 0 дополнительных → Точно не Kafka

🔄 Альтернативы Kafka

Kafka — не единственное решение. Вот популярные альтернативы и когда их выбрать.

RabbitMQ
Message Broker
Классический брокер сообщений. Проще в настройке, богаче паттерны маршрутизации (routing, exchanges). Лучше для очередей задач.
Проще старт Гибкий routing Ниже throughput
Redis Streams
In-memory + Streams
Если уже используете Redis — Streams даёт Kafka-like функционал. Consumer groups, persistence, но всё в памяти + диск.
Уже есть Redis Низкая latency Не для Big Data
AWS SQS/SNS
Managed Cloud
Fully managed, не нужно ничего настраивать. SQS для очередей, SNS для pub/sub. Платите за использование.
Zero ops Auto-scale Vendor lock-in
Google Pub/Sub
Managed Cloud
Аналог от Google Cloud. Глобальная доставка, интеграция с BigQuery, Dataflow. Хорош для GCP-стека.
Global scale GCP интеграции Дорого на объёмах
Apache Pulsar
Streaming Platform
Прямой конкурент Kafka от Apache. Разделение storage и compute, geo-replication из коробки, multi-tenancy.
Современнее Kafka Geo-replication Меньше экосистема
NATS
Lightweight Messaging
Ультра-легковесный и быстрый. Идеален для IoT, edge computing, Kubernetes-native окружения. JetStream добавляет persistence.
Супер быстрый Легковесный Меньше фич

Сравнительная таблица

Критерий Kafka RabbitMQ Redis Streams Pulsar
Throughput Миллионы msg/sec Десятки тысяч Сотни тысяч Миллионы msg/sec
Latency ~5ms ~1ms <1ms ~5ms
Сложность Высокая Низкая Низкая Высокая
Хранение Недели/месяцы До обработки Ограничено RAM Неограниченно
Replay ✅ Да ❌ Нет ✅ Да ✅ Да
Экосистема Огромная Большая Redis экосистема Растущая
💡 Краткая рекомендация

Очередь задач: RabbitMQ или Redis
Event streaming, высокие нагрузки: Kafka или Pulsar
Не хочу поддерживать: AWS SQS/SNS или Google Pub/Sub
Уже есть Redis: Redis Streams
IoT / Edge: NATS

Частые вопросы (FAQ)

Нет. Kafka — это распределённый журнал (log). Она хранит данные, но не предоставляет SQL, индексы, сложные запросы. Данные можно только читать последовательно. Используйте базы данных для хранения состояния, Kafka — для передачи событий.
Self-hosted: 3 сервера минимум (для отказоустойчивости), ~$300-500/месяц на облаке + время DevOps на поддержку.

Managed (Confluent Cloud, AWS MSK): от $200/месяц за маленький кластер до $5000+/месяц за production-ready. Но вы не тратите время на операционку.
При правильной настройке — практически невозможно. Используйте acks=all при записи, replication.factor >= 3, и min.insync.replicas=2. Сообщение будет подтверждено только когда записано на несколько брокеров.
Для новых проектов — нет. Kafka 3.0+ поддерживает режим KRaft (Kafka Raft), который не требует ZooKeeper. Это проще в настройке и поддержке. ZooKeeper будет deprecated.
Популярные решения:
Kafka UI — бесплатный веб-интерфейс
Prometheus + Grafana — метрики и алерты
Confluent Control Center — коммерческое решение
Datadog / New Relic — если уже используете

Ключевые метрики: consumer lag, under-replicated partitions, request latency, disk usage.
RabbitMQ — если нужна простая очередь задач, сложная маршрутизация, низкие latency, и вы не готовы к сложности Kafka.

Kafka — если нужен event streaming, replay событий, очень высокий throughput, долгое хранение, или уже есть экспертиза.

Можно использовать оба: RabbitMQ для очередей задач, Kafka для событий.

📋 Резюме: Apache Kafka

🎯
Для чего
Event Streaming, микросервисы
📈
Масштаб
10K+ msg/sec, 5+ сервисов
Throughput
Миллионы сообщений/сек
🛠️
Сложность
Высокая, нужна экспертиза
💰
Альтернативы
RabbitMQ, Pulsar, Redis
Главный плюс
Надёжность + производительность
🎓 Что дальше?

1. Попробуйте локально — docker-compose из статьи
2. Изучите Kafka Streams — обработка потоков без отдельного фреймворка
3. Посмотрите на Schema Registry — версионирование схем сообщений
4. Почитайте "Kafka: The Definitive Guide" от Confluent (бесплатно)
5. Рассмотрите managed решения — Confluent Cloud, AWS MSK, если не хотите ops

© 2025 • Написано для разработчиков, которые ценят своё время

Apache Kafka® is a registered trademark of the Apache Software Foundation