RabbitMQ или Kafka: что выбрать
Два инструмента, которые постоянно ставят рядом, хотя они решают разные задачи — разбираемся, в чём настоящая разница.
RabbitMQ — брокер очередей: сообщение доставляется потребителю и после подтверждения удаляется. Kafka — распределённый лог: события пишутся в файл-подобную структуру, хранятся заданный срок и читаются любым числом потребителей столько раз, сколько нужно.
Главное различие: кто помнит, что прочитано
Если запомнить из урока одну вещь — пусть это будет она. В RabbitMQ состояние чтения хранит брокер. Он знает, какое сообщение кому отдано и по какому пришёл ack; подтверждённое сообщение из очереди исчезает. Очередь — это «список дел», который постепенно пустеет.
В Kafka состояние чтения хранит потребитель (в виде offset — номера позиции в логе). Само сообщение никуда не девается: оно лежит в партиции, пока не истечёт retention (например, 7 дней). Прочитать его можно повторно — достаточно отмотать offset назад. Лог — это «журнал событий», который не пустеет от чтения.
Отсюда растут все остальные отличия. Kafka умеет реплей (перечитать историю с начала) — потому что она ничего не удаляет. RabbitMQ реплей не умеет — потому что удаляет. Зато RabbitMQ умеет сложную маршрутизацию на стороне брокера и точечные подтверждения каждого сообщения — потому что он и так следит за судьбой каждого из них.
RabbitMQ: маршрутизация как суперсила
Издатель в RabbitMQ публикует не в очередь, а в exchange, и брокер сам решает, куда положить копии. Правила описываются привязками:
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
channel = connection.channel()
# topic-обменник умеет маршрутизировать по шаблону ключа
channel.exchange_declare(exchange="orders", exchange_type="topic", durable=True)
channel.queue_declare(queue="billing", durable=True)
channel.queue_declare(queue="warehouse", durable=True)
channel.queue_declare(queue="audit", durable=True)
# бухгалтерии — только оплаченные заказы
channel.queue_bind(queue="billing", exchange="orders", routing_key="order.*.paid")
# складу — только заказы из московского региона
channel.queue_bind(queue="warehouse", exchange="orders", routing_key="order.msk.*")
# аудиту — вообще всё
channel.queue_bind(queue="audit", exchange="orders", routing_key="order.#")
channel.basic_publish(exchange="orders", routing_key="order.msk.paid", body=b"{}")
# это сообщение попадёт сразу в три очереди: billing, warehouse и audit
Обратите внимание: издатель не знает ни про billing, ни про warehouse. Он просто сообщает ключ order.msk.paid. Вся логика «кому это интересно» живёт в брокере и меняется без единой строчки кода — хоть из веб-панели. В Kafka такой логики нет: продюсер пишет в конкретный топик, и разбирать «моё/не моё» потребитель обязан сам.
Второй козырь — очередь как список задач с честной конкуренцией. Запустили десять воркеров на одну очередь — RabbitMQ раздаёт им сообщения по одному, кто освободился, тот и получил следующее. Медленный воркер просто возьмёт меньше задач. В Kafka параллелизм жёстко ограничен числом партиций: 3 партиции — максимум 3 активных потребителя в группе, четвёртый будет простаивать.
Kafka: лог, который помнит всё
from kafka import KafkaConsumer
consumer = KafkaConsumer(
"user-events",
bootstrap_servers="localhost:9092",
group_id="analytics-v2", # новая группа читает топик с самого начала
auto_offset_reset="earliest", # ...потому что offset у неё ещё не сохранён
)
for msg in consumer:
print(msg.partition, msg.offset, msg.value)
Вот сценарий, ради которого выбирают Kafka. Аналитики нашли баг в расчёте воронки и переписали агрегатор. Им нужно пересчитать метрики за последние полгода. С Kafka это одна строчка: новая consumer group, auto_offset_reset="earliest", и все события за retention-период проезжают через новый код заново. Данные никуда не делись — они лежат в логе.
С RabbitMQ этот сценарий невозможен в принципе: события за полгода давно подтверждены и удалены. Максимум, что у вас есть, — то, что вы сами предусмотрительно сложили в базу или в S3.
Второй сильный ход Kafka — пропускная способность. Она пишет сообщения последовательно в файл и отдаёт потребителям пачками, почти не тратя CPU. Сотни тысяч событий в секунду на скромном кластере — рабочая цифра. RabbitMQ, который для каждого сообщения ведёт учёт доставки и ack, живёт в другом порядке величин: десятки тысяч сообщений в секунду на узел — уже хороший результат. Для 99% бизнес-задач этого хватает с огромным запасом, но кликстрим на 300 тысяч событий в секунду в RabbitMQ пихать не стоит.
Честное сравнение
| Критерий | RabbitMQ | Kafka |
| Модель | Очередь: прочитал и подтвердил — сообщение удалено | Лог: сообщение живёт весь retention, чтение его не удаляет |
| Кто помнит позицию чтения | Брокер (per-message ack) | Потребитель (offset) |
| Перечитать историю | Нельзя | Да, это штатный сценарий |
| Маршрутизация | Богатая: direct / topic / fanout / headers, привязки на брокере | Нет: продюсер пишет в топик, фильтрует потребитель |
| Параллелизм потребителей | Сколько угодно воркеров на одну очередь | Не больше числа партиций в группе |
| Порядок сообщений | В пределах очереди при одном потребителе | Строгий в пределах партиции (ключ → партиция) |
| Приоритеты, TTL, отложенная доставка | Есть из коробки | Нет, надо городить самому |
| Пропускная способность | Десятки тысяч сообщений/с на узел | Сотни тысяч и выше |
| Порог входа в эксплуатацию | Низкий: один контейнер, веб-панель | Выше: кластер, партиции, ребалансировки, мониторинг лага |
Как это работает: три вопроса вместо холивара
На собеседовании и в реальном проектировании выбор сводится к трём вопросам.
1. Это задача или факт?
«Отправь письмо пользователю 42», «сделай превью для видео», «пересчитай баланс» — это задача (command). У неё один исполнитель, её надо выполнить один раз и подтвердить. Это RabbitMQ.
«Пользователь 42 зарегистрировался», «товар добавлен в корзину», «страница просмотрена» — это факт (event). Он уже случился, слушателей может быть сколько угодно, и завтра появится ещё один. Это скорее Kafka — особенно если фактов много и их захотят перечитывать.
2. Понадобится ли перечитать историю?
Если ответ «да» или «наверное, аналитики попросят» — это сильный аргумент за Kafka. Если события живут ровно до обработки и никому потом не нужны — RabbitMQ проще во всём.
3. Какой у вас порядок нагрузки?
Тысячи сообщений в секунду — оба справятся, выбирайте по удобству. Сотни тысяч — RabbitMQ будет больно. Десятки сообщений в минуту — Kafka будет избыточным кластером, который вы будете обслуживать ради трёх писем в час.
И главное: это не «или-или». Во многих компаниях спокойно живут оба: Kafka собирает поток событий и кормит аналитику, а RabbitMQ разносит фоновые задачи между сервисами. Каждый занят тем, для чего создан.
Частые ошибки
- Брать Kafka «потому что все берут». Кластер Kafka — это ZooKeeper или KRaft, партиции, ребалансировки, мониторинг consumer lag и человек, который во всём этом разбирается. Если у вас 500 писем в день, RabbitMQ в одном контейнере закроет задачу за вечер.
- Ждать от RabbitMQ реплея. «А давайте перечитаем очередь за прошлый месяц» — так нельзя. Подтверждённые сообщения удалены навсегда. Нужна история — пишите её в базу отдельно или берите лог.
- Ждать от Kafka маршрутизации. Попытки сделать «топик на каждый тип события с хитрым фильтром» кончаются сотнями топиков и болью. Фильтрация — работа потребителя.
- Забыть про партиции при выборе Kafka. Создали топик с одной партицией — получили ровно одного работающего потребителя в группе, сколько бы вы их ни запустили. Число партиций легко увеличить, но нельзя уменьшить.
- Сравнивать по бенчмаркам вместо задач. «Kafka быстрее» — правда, но бессмысленная, если вам нужно 200 сообщений в секунду и приоритетная очередь.
Итоги
- RabbitMQ — очередь: брокер помнит доставку, сообщение исчезает после ack. Kafka — лог: позицию помнит потребитель, сообщение живёт весь retention.
- RabbitMQ силён в маршрутизации (topic/fanout/direct), приоритетах, TTL и в раздаче задач конкурирующим воркерам.
- Kafka сильна в потоке событий, огромной пропускной способности и реплее истории.
- Эвристика: задача с исполнителем → RabbitMQ, факт для многих подписчиков с возможным перечитыванием → Kafka.
- Оба инструмента прекрасно уживаются в одной системе — выбор делается на уровне конкретного потока данных, а не всей компании.