English translation is not available yet. Showing Russian content.

Почему Kafka лучше RabbitMQ для event streaming?

Краткий тезис

Kafka превосходит RabbitMQ в сценариях event streaming благодаря встроенной долговременной персистентности, возможности повторного воспроизведения (replay) исторических данных и гораздо более высокой пропускной способности (до миллионов сообщений в секунду). RabbitMQ, будучи классическим message broker, оптимизирован для короткоживущих сообщений, гибкой маршрутизации и RPC-подобных взаимодействий, но не предназначен для хранения и переигрывания потока событий. Выбор между ними сводится к задаче: streamingKafka, task queue / RPC → RabbitMQ.


1. Терминология и контекст

Event streaming (потоковая обработка событий) — архитектура, в которой события (изменения состояния, логи, транзакции) непрерывно записываются в упорядоченный журнал и могут быть прочитаны множеством потребителей в реальном времени или с задержкой.

Message queue (очередь сообщений) — классическая модель «точка-точка» или «издатель-подписчик», где сообщения временно хранятся до их обработки одним из потребителей, после чего удаляются.

Apache Kafka — распределённая платформа для event streaming, основанная на журнале (commit log). Сообщения сохраняются на диске в течение настраиваемого времени (retention) и могут быть перечитаны.

RabbitMQ — традиционный message broker, реализующий протокол AMQP 0-9-1, ориентированный на гарантированную доставку, маршрутизацию через exchanges и очереди.

Ключевое различие: Kafka хранит события как immutable log (неизменяемый журнал), RabbitMQ — как временные очереди с удалением после подтверждения.


2. Сравнительная таблица Kafka vs RabbitMQ

ХарактеристикаKafkaRabbitMQ
Модель храненияLog (журнал) на дискеОчередь в памяти / на диске по желанию
Retention (время хранения)Дни/годы (настраивается)Секунды/минуты (пока сообщение не подтверждено)
Replay (повторное чтение)Да, любое сообщение по offsetНет (после ack удаляется)
Пропускная способностьОчень высокая (>1M msg/sec на кластер)Средняя (~50-100k msg/sec)
Упорядочивание сообщенийСтрогое внутри партицииГлобальное только для одного потребителя
МаршрутизацияПростая (topic → партиция)Гибкая (exchanges + routing keys)
Типичные сценарииEvent streaming, CDC, лог-агрегация, метрикиRPC, task queues, работа с транзакциями
Управление состоянием потребителейOffset (авто или ручной)Acknowledgement (ack/nack)
Масштабирование потребленияПартиции → группы потребителейКонкурирующие потребители (competing consumers)

3. Почему Kafka выигрывает для event streaming

3.1 Долговременное хранение (Retention)

В Kafka retention (время хранения сообщений) настраивается отдельно для каждого топика — от минут до месяцев и даже лет. Сообщения не удаляются автоматически после прочтения, а живут до истечения retention или превышения размера (log.retention.bytes). Это позволяет потребителям «отставать» без потери данных.

В RabbitMQ стандартная очередь после подтверждения (ack) удаляет сообщение. Хотя можно включить durable queues и сохранять на диск, retention не предназначен для длительного хранения — очередь оптимизирована под быструю доставку, а не под архив.

Пример настройки retention в Kafka (конфигурация топика):

--config retention.ms=604800000  # 7 дней
--config cleanup.policy=compact   # или delete / compact

3.2 Повторное воспроизведение (Replay)

Поскольку Kafka хранит сообщения, любой новый или отставший потребитель может начать читать с любого смещения (offset) — с начала топика, с конкретной временной метки или с последнего сохранённого состояния. Это критически важно для:

  • CDC (Change Data Capture) — повторная обработка изменений БД после падения аналитического слоя.
  • Восстановление после сбоя — перечитывание событий с момента последнего успешного чекпоинта.
  • A/B-тестирование моделей — подача одного и того же исторического стрима двум разным обработчикам.

В RabbitMQ, чтобы получить ту же функциональность, потребуется специальная надстройка (например, Shovel или Federation), и всё равно это не даёт произвольного чтения из прошлого — сообщения уже удалены.

3.3 Пропускная способность (Throughput)

Kafka спроектирована для high-throughput за счёт:

  • Пакетной записи/чтения — сообщения не передаются по одному, а группируются в батчи.
  • Последовательного доступа к диску — запись в лог (appending) практически не требует seek, что даёт скорость, близкую к линейной.
  • Масштабирования партиций — параллелизм чтения/записи равен числу партиций, которые могут быть распределены по брокерам.

RabbitMQ использует протокол AMQP, который ориентирован на атомарную доставку каждого сообщения. Он может быть ускорен через confirms и гарантии доставки, но архитектурно не рассчитан на пропуск, превышающий сотни тысяч сообщений в секунду (на одном узле).

3.4 Персистентность (Persistence)

Kafka по умолчанию сохраняет каждое сообщение на диск (durable commit log). Даже при внезапном отказе брокера все уже записанные события восстанавливаются.

RabbitMQ по умолчанию хранит сообщения в памяти, что даёт высокую скорость, но риск потери. Для гарантии нужно объявлять очереди как durable и публиковать с persistent delivery mode — это снижает производительность.

3.5 Упорядочивание сообщений (Ordering)

В Kafka порядок сообщений гарантирован внутри одной партиции. Если требуется глобальный порядок для конкретного ключа (например, все события одного пользователя), достаточно направить их в одну партицию.

В RabbitMQ порядок сохраняется только для одного потребителя при отсутствии переотправок (reject). При нескольких потребителях или после requeue порядок нарушается. Для строгого упорядочивания приходится использовать single active consumer, что снижает параллелизм.


4. Когда выбирать RabbitMQ

Несмотря на явные преимущества Kafka для streaming, RabbitMQ остаётся лучшим выбором в сценариях:

СценарийПочему RabbitMQ
RPC (удалённый вызов процедур)Встроенная reply-to очередь, корреляционные ID, время ожидания
Task queues (распределённые задачи)Гибкая маршрутизация через exchanges, dead letter queues, лёгкие ack
Много типов сообщений, сложная маршрутизацияExchanges (direct, topic, fanout, headers) + binding keys
Низкая латентность (<10ms)За счёт хранения в памяти и лёгкого протокола
Небольшой объём данных (<10k msg/sec)Простота развёртывания, низкие требования к ресурсам

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


5. Пример архитектуры event streaming на Kafka

Рассмотрим систему CDC (Change Data Capture) для базы данных PostgreSQL.

PostgreSQL WAL → Debezium (CDC Source) → Kafka (топик "db.orders") → Sink Connector (например, в ClickHouse)
  • Debezium непрерывно читает Write-Ahead Log (WAL) и публикует каждое изменение (INSERT/UPDATE/DELETE) как событие в Kafka.
  • Kafka хранит события 7 дней. Если аналитическая система временно недоступна, она, восстановившись, может перечитать топик с любой позиции.
  • Несколько потребителей (ClickHouse, Elasticsearch, Spark Streaming) параллельно читают один топик, каждый со своим offset.

Почему не RabbitMQ CDC требует replay: после сбоя ClickHouse должен начать с последнего подтверждённого события. В RabbitMQ эти события уже удалены из очереди после ack другим потребителем (или тем же — после чтения). Kafka же сохраняет историю, позволяя «перемотать» стрим назад.


6. Пет-проект для закрепления

Задача: Разработать мини-систему для анализа пользовательских кликов в реальном времени.

Инструменты:

Шаги:

  1. Разверните Kafka и RabbitMQ в Docker.
  2. Создайте Kafka-топик clicks (1 партиция для простоты, retention 1 час).
  3. Напишите producer на Python, отправляющий 1000 случайных кликов в секунду в Kafka.
  4. Напишите consumer для Kafka, который раз в 5 секунд печатает агрегированную статистику (количество кликов за последние 10 секунд, используя time-window).
  5. Аналогично сделайте для RabbitMQ: объявите очередь clicks_queue, настройте consumer. Сравните поведение при отключении consumer на 30 секунд:
    • В Kafka после повторного запуска consumer прочитает пропущенные события (offset хранится).
    • В RabbitMQ сообщения будут потеряны (если queue не durable или если сообщения не персистентны) либо накопятся, но будут удалены после ack.
  6. Измените код, чтобы Kafka-consumer мог начать читать заново с самого старого offset (replay). Попробуйте повторить то же самое с RabbitMQ — убедитесь, что это невозможно.

Ожидаемый результат:

  • Вы на практике увидите разницу в поведении при сбоях.
  • Поймёте, почему в real-time streaming systems (ClickHouse, Spark, Flink) часто выбирают Kafka: она даёт гарантию, что данные не будут потеряны и их можно перечитать.

7. Связь с другими вопросами

ВопросТема
850Архитектура Agentic RAG: роль event streaming в pipeline
851Выбор брокеров для RAG-систем (Kafka, RabbitMQ, Redis)
853Сравнение Kafka и Pulsar для event streaming
855Транзакции и exactly-once в Kafka
856Мониторинг и observability event streaming
865CDC (Change Data Capture) в RAG-пайплайнах

8. Навигация

  • Предыдущий: 853 (предполагаемый предыдущий вопрос — 853, если он существует; в данном курсе нумерация 850-859, так что 854, предыдущий 853)
  • Следующий: 855
  • Индекс: 00. Индекс разборов

Навигация