Messaging & Queues

Apache Kafka

Apache Kafka — распределённая платформа потоковой передачи событий: продюсеры пишут сообщения в топики, а консьюмеры читают их из лога на диске в своём темпе.

Что такое Apache Kafka

Apache Kafka (в разговоре — «кафка») — распределённая платформа потоковой передачи событий. Продюсеры пишут сообщения в топики, Kafka складывает их на диск в виде упорядоченного лога, а консьюмеры читают этот лог сами и в своём темпе. Проект вырос из внутренней разработки LinkedIn, с 2011 года развивается в Apache Software Foundation; сервер написан на Scala и Java, работает на JVM, слушает порт 9092.

Простыми словами: Kafka — не почтовый ящик, а журнал. Обычный брокер сообщений удаляет сообщение, как только его забрали. Kafka дописывает события в конец файла и хранит их заданный срок независимо от того, кто и сколько раз их прочитал. Отсюда и все её свойства: можно перечитать историю, можно подключить нового читателя задним числом, можно читать один поток десятью сервисами сразу.

Топики, партиции и offset

Топик — именованный поток событий (orders, clicks). Физически он нарезан на партиции, и каждая партиция — независимый append-only лог. У сообщения внутри партиции есть offset: порядковый номер, который не меняется никогда.

Топик "orders", 3 партиции:

P0: [0][1][2][3][4]        ← продюсер всегда дописывает в конец
P1: [0][1][2]
P2: [0][1][2][3][4][5]
          ↑
      консьюмер читает с offset=2 и сам двигает курсор

Партицию выбирает ключ сообщения: hash(key) % число_партиций. Отсюда главное практическое правило — порядок гарантирован только внутри партиции, а не внутри топика. Нужен строгий порядок событий по клиенту — ставьте key = client_id: все его события лягут в одну партицию и будут прочитаны последовательно. Глобального порядка по всему топику Kafka не даёт и не обещает.

Consumer group: как масштабируется чтение

Консьюмеры объединяются в группу (group.id), и Kafka распределяет партиции между её участниками так, что одну партицию в каждый момент читает ровно один консьюмер группы. Следствие: число партиций — это потолок параллелизма. Шесть партиций — максимум шесть работающих консьюмеров, седьмой будет простаивать.

Разные группы читают тот же топик независимо и не мешают друг другу: один поток событий одновременно уходит и в биллинг, и в аналитику, и в поиск.

Прогресс группы — это закоммиченный offset. Разрыв между последним записанным и закоммиченным offset называется consumer lag и служит главной метрикой здоровья: растёт lag — консьюмеры не успевают за продюсерами. Следить за ним стоит с самого начала, наравне с обычным health check.

Надёжность: репликация и acks

Каждая партиция реплицируется на несколько брокеров: один лидер, остальные — follower'ы. Реплики, догнавшие лидера, образуют ISR (in-sync replicas).

acks Когда запись считается успешной Риск
0 Сразу после отправки Потеря при любом сбое
1 Лидер записал к себе Потеря, если лидер упал до репликации
all Записали все реплики из ISR Минимальный, ценой задержки

Рабочий продакшн-набор: acks=all, replication.factor=3, min.insync.replicas=2кластер переживает потерю одного брокера без потери данных. Плюс enable.idempotence=true, чтобы повторы продюсера при таймаутах не порождали дубли. Координацию кластера в актуальных версиях обеспечивает встроенный KRaft, отдельный ZooKeeper больше не нужен.

Хранение: сообщения живут по таймеру

retention.ms=604800000    # 7 дней — значение по умолчанию
retention.bytes=-1        # без лимита на размер партиции
cleanup.policy=delete     # delete — удалять старое по сроку
                          # compact — хранить последнее значение по каждому ключу

Compaction превращает топик в снимок состояния: для каждого ключа остаётся только самое свежее сообщение — так хранят, например, актуальный профиль пользователя. Возможность перечитать историю обычно и есть причина выбрать Kafka: новый сервис поднимается, проигрывает поток с offset=0 и строит своё состояние, никому не мешая.

Kafka vs RabbitMQ

Apache Kafka RabbitMQ
Модель Лог: сообщение остаётся после чтения Очередь: сообщение исчезает после ack
Кто маршрутизирует Консьюмер сам выбирает топик и offset Брокер — через exchange и routing key
Перечитать историю Да, сдвигом offset Нет
Порядок Внутри партиции Внутри очереди
Сильная сторона Поток событий, высокая пропускная способность Гибкая раздача задач воркерам, приоритеты, retry

Когда Kafka уместна, а когда нет

  • Да: событийная шина между микросервисами, сбор кликов, логов и метрик, поставка данных в ClickHouse или DWH, CDC-поток изменений из PostgreSQL, пересчёт истории на новой логике.
  • Нет: десяток задач в сутки, приоритеты сообщений, отложенная доставка «через 30 минут», индивидуальный retry каждого сообщения. Здесь Kafka — лишняя сложность, а RabbitMQ или NATS решают задачу проще.

По ресурсам Kafka упирается в диск и сеть, а не в CPU: она пишет последовательно и отдаёт данные из page cache. Значит — NVMe под логи, запас по пропускной способности сети и минимум три брокера, иначе репликация теряет смысл.

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

  • Брокеры сообщений — общий класс систем, к которому относится Kafka
  • RabbitMQ — брокер с противоположной моделью: очередь вместо лога
  • NATS — лёгкая альтернатива, когда не нужна экосистема Kafka
  • Микросервисы и монолит — архитектура, ради которой обычно ставят Kafka
  • ClickHouse — типичный приёмник событий из Kafka
  • Кластер — Kafka разворачивается только кластером

Готовы запустить GPU-задачу?

Запустить GPU-сервер