RabbitMQ или Redis: куда нести свои сообщения?
Представим, что нашему приложению нужно сделать что-то тяжелое: отправить письмо, сгенерировать PDF-инвойс или выгрузить отчет. Если делать это прямо в коде, пока пользователь ждет ответа, сайт будет тормозить. Чтобы этого не происходило, задачи отправляют в «почтовый ящик» — брокер сообщений.
Самые популярные ящики — RabbitMQ и Redis. Они решают одну задачу, но делают это совершенно по-разному.
Что такое RabbitMQ?
Это настоящий специализированный почтовый узел. Он живет по правилам протокола AMQP.
Код он не кидает сообщение сразу в очередь. Он кидает его в «почтовый ящик» — Exchange. А уже этот ящик по своим правилам (например, по теме письма) сам раскладывает копии сообщения по разным физическим очередям.
Когда воркер забирает задачу и успешно ее делает, он отправляет брокеру подтверждение. Если воркер упал, не успев подтвердить, RabbitMQ отдаст эту задачу другому. Ничего не потеряется.
Когда это нужно: микросервисы, финансовые транзакции, сложные интеграции, где нельзя потерять ни одного байта.
Что такое Redis?
Это швейцарский нож. Все знают его как кэш, но он умеет работать и как очередь. Ему не нужны сложные Exchange, он работает с простыми структурами данных прямо в оперативной памяти.
Самый частый способ сделать очередь на Redis — использовать Lists:
Продюсер (кладет задачу):
`LPUSH jobs:email '{"to": "user@example.com", "text": "Hellо"}
Воркер (забирает задачу):
`BRPOP jobs:email 0`
(Команда BRPOP говорит Redis: «Стой и жди здесь, пока в списке не появится задача. Как появится — сразу отдавай мне»).
А если нужно, чтобы несколько воркеров читали один поток задач и умели подтверждать их выполнение (как в RabbitMQ), используют Streams (появились в Redis 5.0). Это уже почти как маленький Kafka, но внутри Redis.
Когда это нужно: фоновые задачи в веб-приложении, уведомления в реальном времени, инвалидация кэша, когда Redis в проекте уже есть и не хочется тянуть лишнее.
Плюсы и минусы на пальцах
RabbitMQ
* Плюс: Надежность. Это его главная работа. Сообщения живут на диске, есть dead letter queues (если задача упала 5 раз, она уйдет в спецкорзину), есть транзакции.
* Плюс: Гибкость. Можно строить сложные схемы: один заказ улетает одновременно в очередь логистики, бухгалтерии и маркетинга.
* Минус: Сложность. Его нужно ставить, мониторить, понимать, как работают биндинги и экспоненциальные задержки. Он ест больше ресурсов.
* Минус: Скорость. Он медленнее Redis, так как постоянно общается с диском и управляет сложным состоянием очередей.
Redis
* Плюс: Скорость. Всё в оперативной памяти. Задержки измеряются микросекундами. Это самый быстрый вариант.
* Плюс: Простота. Если у тебя уже есть Redis для кэша, очередь появляется за 5 минут настройки драйвера в Laravel или Spring. Никаких новых серверов.
* Минус: Память. Redis держит всё в RAM. Если очередь раздуется и память кончится, Redis начнет вытеснять старые данные (если не настроить лимиты жестко), и ты потеряешь задачи.
* Минус: Надежность «из коробки». Если ты не включил AOF-лог (запись на диск при каждом изменении), то при внезапном выключении сервера последние задачи, которые не успели записаться на диск, пропадут.
Как выбрать?
Если мы строим взрослый бэкенд из кучи сервисов, которые обмениваются событиями (пользователь оплатил — сервис оплаты стучит в сервис уведомлений, сервис логистики и CRM) — берем RabbitMQ. Он создан для этого.
Если у нас обычное веб-приложение, где нужно просто «сделать фоново ресайз картинки и отправить письмо», и Redis у нам уже стоит для сессий — берем Redis. Не усложняем архитектуру.