10. Сравнение и контекст: RabbitMQ vs Kafka vs Redis
Цель темы — научиться выбирать инструмент под задачу. RabbitMQ, Kafka и Redis закрывают похожие потребности (асинхронность/события), но у них разные гарантии, модели потребления и эксплуатационные компромиссы. Ниже — сравнение, примеры типовых сценариев и production‑критерии выбора.
Короткая карта выбора
| Если нужно | Чаще выбирают | Почему |
|---|---|---|
| Очередь задач, fair dispatch, сложная маршрутизация | RabbitMQ | Exchange/queue/binding, work queues, DLQ/TTL, простая интеграция, низкий порог входа. |
| Поток событий с ретеншном, replay, высокая пропускная | Kafka | Log‑модель, consumer groups, хранение и повторное проигрывание, партиции и масштабирование. |
| Очень быстрый ephemeral pub/sub или простые стримы рядом с кешем | Redis | Минимальная задержка, простота, но ограничения по гарантиям/ретеншну (зависит от режима). |
Модель данных и потребления
RabbitMQ
- Единица — сообщение в очереди.
- Consumer обычно “забирает” сообщение, после ack оно исчезает из очереди.
- Гарантия чаще at-least-once (дубликаты возможны) → нужна идемпотентность.
- Сильные стороны: маршрутизация (direct/topic/fanout/headers), DLX/DLQ, TTL, backpressure.
Kafka
- Единица — append-only log (топик → партиции).
- Consumer “читает offset” и может делать replay (переигрывать события).
- Естественно подходит для event sourcing, аналитики, интеграционных шин.
- Порядок гарантируется внутри партиции.
Redis
- Redis Pub/Sub: сообщения не сохраняются, “кто не слушает — тот пропустил”.
- Redis Streams: есть ретеншн и consumer groups, но модель и эксплуатация отличаются от Kafka.
Гарантии и порядок
| Система | Порядок | Дубликаты | Replay |
|---|---|---|---|
| RabbitMQ | В основном “по очереди”, но зависит от consumer’ов и prefetch | Возможны (типично) | Нет “из коробки” как в Kafka |
| Kafka | Внутри партиции | Возможны (зависит от обработки offsets) | Да (core‑фича) |
| Redis Pub/Sub | Нет гарантий доставки | Возможны потери | Нет |
| Redis Streams | Внутри stream (и по группам) | Возможны (при retries/claims) | Да (в пределах ретеншна) |
Production вывод: “exactly-once” чаще достигается не брокером, а идемпотентной бизнес‑логикой и корректной обработкой ошибок.
Типовые use-cases (что лучше где)
1) Фоновая обработка задач (job queue)
RabbitMQ обычно лучший старт:
- work queue + prefetch + ack
- DLQ и retry через TTL/DLX
Kafka тут тоже возможна, но чаще усложняет “простую очередь задач”.
2) Интеграционные события и аналитика
Kafka сильнее:
- хранение событий, replay, интеграция с stream‑обработкой
- удобно подключать новых потребителей “задним числом”
3) Быстрые ephemeral события внутри одного домена
Redis Pub/Sub может быть достаточно, если:
- потеря части сообщений допустима
- нет требований к ретеншну/повторной обработке
Если потеря недопустима — использовать RabbitMQ/Kafka/Streams.
Эксплуатация и стоимость владения
RabbitMQ
- проще начать и сопровождать небольшие/средние нагрузки
- требует дисциплины: DLQ, prefetch, лимиты, мониторинг
- HA через quorum queues/кластер и правильные диски
Kafka
- выше порог входа и требования к эксплуатации (кластер, партиции, ретеншн)
- очень хороша для больших потоков событий и replay
Redis
- проще всего как часть уже существующего Redis‑стека
- но нужно чётко понимать ограничения по надёжности
Небольшие примеры “в коде”: как отличается подход
RabbitMQ: consumer ack (идея)
# ack после успешной обработки -> at-least-once + идемпотентность
ch.basic_ack(delivery_tag=method.delivery_tag)
Kafka: offset commit (идея)
process(message)
commit(offset)
Если commit не произошёл — сообщение может быть прочитано снова (дубликат), поэтому идемпотентность всё равно нужна.
Production критерии выбора (чеклист)
- Нужен ли replay и как долго хранить события?
- Нужна ли маршрутизация (topic exchange, multiple queues) или достаточно “топик → группа”?
- Допустима ли потеря сообщений?
- Нужна ли строгая доставка “задача выполнена ровно один раз” (обычно → идемпотентность + дедуп)?
- Какой ожидаемый throughput/latency?
- Кто и как будет сопровождать кластер (SRE/Platform)?