Потоковая обработка
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 для конкретного сценария
Предварительные знания
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 |
| Delivery | At-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 |
| Ordering | FIFO внутри одной очереди |
| Delivery | At-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 вместо всего остального.
| Свойство NATS | Core | JetStream |
|---|---|---|
| Persistence | Нет | Да (файловая система) |
| Delivery | At-most-once | At-least-once, exactly-once |
| Consumer groups | Queue groups | Durable 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.
| Критерий | Kafka | RabbitMQ | NATS JetStream |
|---|---|---|---|
| Throughput | Миллионы msg/s | Десятки тысяч msg/s | Сотни тысяч msg/s |
| Latency (p99) | 2-10 мс | ~1 мс | ~1 мс |
| Ordering | Per-partition | Per-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