Потоковая обработка

Message Brokers: Kafka vs RabbitMQ vs NATS

Цели урока

  • Понимать архитектуру Kafka как распределённого лога (offset, partition, consumer group)
  • Различать routing модели RabbitMQ (Direct, Fanout, Topic, Headers exchanges)
  • Выбирать между NATS Core и JetStream исходя из требований к persistence
  • Принимать архитектурное решение Kafka vs RabbitMQ vs NATS для конкретного сценария

Предварительные знания

  • Event-Driven Architecture

LinkedIn создал Kafka в 2010 чтобы обрабатывать сотни миллионов событий в день - и сегодня через него проходит 7 триллионов сообщений. Pivotal создала RabbitMQ для гарантированной доставки в enterprise-системах. NATS появился для cloud-native мира, где нужен один бинарник на 15 MB без зависимостей. Три философии, три архитектуры. Выбор определяет всё.

  • **Kafka в LinkedIn** - каждый клик, просмотр, лайк пишется в Kafka; analytics, ML features, real-time personalization
  • **RabbitMQ в банкинге** - гарантированная доставка платёжных поручений с приоритетами и dead letter handling
  • **NATS в Kubernetes** - Synadia NATS как messaging layer для микросервисов, service mesh без sidecar

Jay Kreps и рождение Kafka

Джей Крепс, Нехал Шах и Джун Рао создали Kafka в LinkedIn в 2010 году. Крепс назвал систему в честь Франца Кафки - "система оптимизированная для записи" как отсылка к писателю, который много писал. В 2011 году LinkedIn открыл исходный код и передал проект Apache Software Foundation. В 2014 году Крепс основал Confluent - компанию, которая сейчас управляет развитием Kafka и строит Confluent Cloud.

Apache Kafka

LinkedIn, 2010. Команда обрабатывает сотни миллионов событий в день - клики, просмотры, лайки. Существующие очереди не справляются. Джей Крепс, Нехал Шах и Джун Рао изобретают Kafka. Не очередь. **Распределённый лог.** Сообщения записываются в конец лога и не удаляются после чтения. Consumer сам отслеживает свою позицию (offset).

**Ключевые концепции Kafka:** Topic - именованный поток данных. Partition - шард топика для параллелизма. Consumer Group - группа consumers, где каждый partition читается ровно одним consumer. Retention - время хранения сообщений (дни, недели, навсегда).

Kafka обеспечивает **ordering within partition**: сообщения с одним key (например, userId) всегда попадают в одну partition и читаются в порядке записи. Глобальный порядок не гарантирован - разные partition-ы параллельны. Именно поэтому LinkedIn может обрабатывать 7 триллионов сообщений в день.

Свойство KafkaЗначение
ThroughputМиллионы msg/sec на кластер
Latency~2-10 мс (p99)
RetentionНастраиваемый: дни, недели, навсегда
OrderingГарантирован внутри partition
DeliveryAt-least-once (по умолчанию), exactly-once (с транзакциями)
ПротоколСобственный бинарный TCP

В чём ключевое отличие Kafka от традиционной очереди сообщений?

RabbitMQ

RabbitMQ - классический **message broker**, реализующий протокол AMQP. Pivotal создала его для enterprise-систем где нужна гарантированная доставка конкретному обработчику. В отличие от Kafka-лога, RabbitMQ - умный брокер: маршрутизирует сообщения через exchanges, удаляет после acknowledge.

**Архитектура RabbitMQ:** Producer -> Exchange -> Queue -> Consumer. Exchange маршрутизирует сообщения в очереди по правилам (bindings). Типы exchanges: **Direct** (по routing key), **Fanout** (во все очереди), **Topic** (по паттерну routing key), **Headers** (по заголовкам).

Сильные стороны RabbitMQ: **flexible routing** (exchanges + bindings), **per-message acknowledge** (гарантия обработки), **priority queues**, **dead letter exchanges** (для необработанных сообщений), **зрелая экосистема** и management UI. Slack использует RabbitMQ для job queues параллельно с Kafka для event streaming.

Свойство RabbitMQЗначение
ThroughputДесятки тысяч msg/sec на ноду
Latency~1 мс (очень низкая для одного сообщения)
RetentionНет - сообщение удаляется после ack
OrderingFIFO внутри одной очереди
DeliveryAt-most-once, at-least-once, или manual ack
ПротоколAMQP 0-9-1, MQTT, STOMP

Какой тип exchange в RabbitMQ отправит сообщение ВСЕМ привязанным очередям?

NATS

NATS - **ультра-легковесный** messaging system, написанный на Go. Бинарник ~15 MB, запускается за миллисекунды, потребляет минимум ресурсов. Там где Kafka требует JVM и гигабайты RAM, NATS запускается даже на Raspberry Pi. Изначально at-most-once (fire-and-forget), но **JetStream** добавил persistence и exactly-once.

**NATS Core** - чистый pub/sub, at-most-once, нет persistence. **NATS JetStream** - persistence, at-least-once/exactly-once, consumer groups, key-value store, object store. JetStream встроен в NATS server - не требует отдельной инфраструктуры.

NATS отлично подходит для IoT (миллионы подключений, маленькие сообщения), микросервисов (service mesh communication), edge computing. С JetStream - для event streaming подобно Kafka, но с гораздо меньшей операционной сложностью. Synadia использует NATS JetStream для cloud-native messaging вместо всего остального.

Свойство NATSCoreJetStream
PersistenceНетДа (файловая система)
DeliveryAt-most-onceAt-least-once, exactly-once
Consumer groupsQueue groupsDurable consumers
ReplayНетДа (по offset, по времени)
Key-Value StoreНетДа (встроенный)
Footprint~15 MB RAM~50 MB RAM

В чём главное преимущество NATS перед Kafka для IoT-сценариев?

Сравнение: когда что выбирать

Каждый брокер оптимизирован под свой сценарий. Нет универсального «лучшего» - есть правильный инструмент для задачи. Kafka доминирует в data streaming, RabbitMQ - в enterprise messaging, NATS - в cloud-native и IoT.

КритерийKafkaRabbitMQNATS JetStream
ThroughputМиллионы msg/sДесятки тысяч msg/sСотни тысяч msg/s
Latency (p99)2-10 мс~1 мс~1 мс
OrderingPer-partitionPer-queue (FIFO)Per-stream
PersistenceДа (лог на диске)ОпциональнаяДа (JetStream)
RoutingПростая (topic/partition)Сложная (exchanges)Subject-based wildcard
Ops сложностьВысокая (кластер, ZK)СредняяНизкая (один бинарник)

**Kafka** - когда данные = asset: event sourcing, analytics pipeline, CDC (change data capture), ML feature store. **RabbitMQ** - когда нужна гарантированная доставка конкретному обработчику: task queues, RPC, notifications. **NATS** - когда нужна простота и скорость: service mesh, IoT, request-reply.

Реальность production: Uber использует Kafka для event streaming плюс собственный Cherami. Slack - Kafka для events и RabbitMQ для job queues. Synadia строит всё на NATS JetStream. Нормально использовать несколько брокеров - каждый решает свою задачу.

Kafka - это очередь сообщений (message queue)

Kafka - это распределённый лог (commit log) с семантикой publish-subscribe. Сообщения НЕ удаляются после чтения - хранятся до истечения retention. Несколько consumer groups читают одни и те же данные независимо.

В классической очереди (RabbitMQ) сообщение доставляется одному consumer и удаляется. В Kafka сообщение - запись в логе, которую могут читать все. Это делает Kafka идеальным для event streaming, replay, CDC, но неудобным для task queues.

Система обработки платежей: сообщение должно быть гарантированно доставлено ровно одному обработчику, с приоритетом и dead letter queue. Лучший выбор:

Ключевые идеи

  • **Kafka** - распределённый лог; высокий throughput, retention, replay; идеален для event streaming и data pipelines
  • **RabbitMQ** - AMQP-брокер; гибкая маршрутизация (exchanges), acknowledgments, priority, DLQ; идеален для task queues
  • **NATS** - ультра-лёгкий; Core (at-most-once, zero config), JetStream (persistence); идеален для IoT, cloud-native, edge
  • Нет «лучшего» - выбор определяется требованиями: data streaming -> Kafka, task queue -> RabbitMQ, lightweight -> NATS

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

Брокеры - инфраструктура для event-driven и stream систем:

  • Event-Driven Architecture — Брокеры - транспорт для events и commands в EDA
  • Batch vs Stream Processing — Kafka - основной источник данных для Flink и Spark Streaming
  • Kafka Streams и Stream Processing — Следующий уровень - обработка потоков прямо внутри Kafka

Вопросы для размышления

  • Kafka хранит данные неделями, но RabbitMQ удаляет после acknowledge. В каких сценариях хранение данных в брокере вредно?
  • При проектировании системы уведомлений (email, push, SMS) - какой брокер выбрать и почему?
  • NATS Core - at-most-once (может потерять сообщение). В каких случаях это приемлемо?

Связанные уроки

  • stream-02 — Event-Driven Architecture - транспортный слой для events и commands
  • stream-01 — Batch vs Stream Processing - контекст для понимания зачем нужен Kafka
  • stream-04 — Kafka Streams и Flink строятся поверх базового понимания Kafka
  • rt-03-sse — SSE endpoint как consumer поверх Kafka topic
  • ds-05 — Репликация в distributed systems - те же trade-offs что и в Kafka partitions
  • cloud-05 — Managed Kafka (Confluent Cloud, MSK) как cloud-native деплой
  • dist-07-transactions
Message Brokers: Kafka vs RabbitMQ vs NATS

0

1

Войти