Очереди и брокеры: Redis, RabbitMQ, Kafka и что ещё бывает на рынке

Очередь задач и брокер сообщений в разговоре часто смешивают в одно слово «очередь», хотя это разные ментальные модели. Первая отвечает на вопрос: «выполни эту работу позже, один раз (с повторами), в воркере». Вторая часто означает: «доставь сообщение подписчикам, возможно нескольким, с маршрутизацией и политикой хранения». Kafka ближе к распределённому журналу, чем к классической очереди в понимании Rabbit. Ниже — как это стыкуется с Laravel и с другими стеками, где технология уместна, а где вы платите сложностью без выигрыша.

Связанные материалы: Потоки событий под нагрузкой · Sail: очереди и RabbitMQ

Содержание


Задача «потом выполнить» и поток «все прочитали лог»

Job queue — вы кладёте задание (отправить письмо, сгенерировать PDF, дернуть внешний API). Ожидание: один воркер заберёт задачу, выполнит, подтвердит. Удобны retry, задержки, приоритеты (в зависимости от брокера), таблица failed_jobs в Laravel.

Message broker в стиле Rabbit — вы публикуете сообщение, брокер маршрутизирует в одну или несколько очередей; разные сервисы подписаны на разные биндинги. Это уже интеграционная шина между сервисами, а не только «отложенный PHP».

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

Путаница начинается, когда в Kafka пытаются вести себя как в Rabbit: «одна задача — один consumer» можно, но вы боретесь с моделью и теряете часть преимуществ лога.


Redis: дефолт Laravel и границы применимости

В экосистеме Laravel Redis — самый частый выбор для QUEUE_CONNECTION=redis: быстро, знакомо, Horizon даёт UI и балансировку воркеров.

Плюсы: низкая латентность, один стек с кэшем и rate limit, простой деплой для средних нагрузок.

Минусы и нюансы:

  • Память: при всплеске очередей Redis растёт; нужны лимиты, мониторинг длины, политика eviction не должна молча съедать ключи очередей.
  • Персистентность: RDB/AOF спасают от части сценариев, но Redis — не Kafka; требования уровня «ни одного сообщения при падении датацентра» требуют явной архитектуры (кластер, реплики, тесты failover).
  • Redis Streams удобны для потокового сценария с группами потребителей; классические lists проще для «одна очередь — пачка воркеров». Laravel job queue под капотом использует структуры, ориентированные на задачи, а не на многодневный immutable log.

Когда избыточно искать замену: небольшой продукт, один сервер, Redis уже есть — не обязательно тащить Rabbit «по учебнику».

Когда мало: жёсткие требования к гарантированной доставке и долгому хранению очереди, сложная маршрутизация между десятками типов сообщений, огромный fan-out — смотрите на Rabbit или Kafka.


RabbitMQ: очереди AMQP и эксплуатация

RabbitMQ реализует AMQP (и другие протоколы): exchange → binding → queue. Подходит и для Laravel (драйвер rabbitmq через пакеты вроде vladimir-yuldashev/laravel-queue-rabbitmq), и как общий брокер для PHP, Python, Go.

Плюсы: гибкая маршрутизация (topic, headers), TTL, dead-letter exchanges, задержки и повторы на уровне брокера, привычная модель «очередь задач / событий между сервисами».

Минусы и нюансы:

  • Эксплуатация: кластеризация, зеркалирование очередей (в зависимости от версии и политики), memory/disk high watermark, понимание prefetch и того, что один «тяжёлый» consumer может задерживать выдачу.
  • Throughput: на экстремальных RPS иногда упираются в тюнинг и топологию; это не магическая «медленная очередь», но и не Kafka по сквозной пропускной способности без дизайна.
  • Для простого «dispatch job» без межсервисной шины Rabbit может быть дороже в сопровождении, чем Redis.

Когда уместен: несколько языков в контуре, нужны чёткие контракты обмена, DLQ, маршрутизация, интеграции с Symfony Messenger или другими AMQP-клиентами.


Kafka: журнал, а не фоновая почта

Apache Kafkaраспределённый лог с партициями. Сообщения имеют offset; consumer group делит партиции между участниками; retention определяет, как долго «лента» доступна для повторного чтения.

Плюсы: очень высокий throughput при правильном партиционировании, много независимых читателей одной темы, реплей для новых сервисов и отладки, естественная база для event-driven архитектуры и стриминга.

Минусы и нюансы:

  • Laravel не считает Kafka «встроенным» драйвером очереди так же, как Redis; обычно нужны отдельные библиотеки или отдельные консьюмеры на другом рантайме, а PHP остаётся продюсером или точечным consumer.
  • Операции: ZooKeeper/KRaft, rebalancing групп, размер партиций, compaction vs delete retention — кривая обучения.
  • Использовать Kafka только чтобы отправить одно письмо раз в час — типичный оверинжиниринг.

Когда уместен: большой объём событий, несколько команд потребляют одну историю, нужны аудит и повторное проигрывание, интеграция с stream processing (Flink, ksqlDB и т.д.).


Что ещё на рынке (кратко)

  • Amazon SQS / SNS — управляемые очереди и pub/sub; в Laravel есть нативный драйвер sqs. Плюс: нет своего брокера. Минус: латентность, модель visibility timeout, стоимость на объёме.
  • Google Pub/Sub, Azure Service Bus — облачные аналоги с разными семантиками доставки и интеграцией с функциями «serverless».
  • NATS / JetStream — лёгкий брокер, популярен в Go-экосистеме; JetStream добавляет персистентность; другая модель, чем у Rabbit.
  • Beanstalkd — простая классика «труба + трубы»; реже встречается в новых проектах, но проста по духу.
  • Managed Kafka (MSK, Confluent Cloud, Aiven) — снимают часть боли с железом, не снимают необходимость дизайна топиков и групп.

Выбор «облако vs своё» — это ещё и вендорный lock-in против ночных дежурств на кластере.


Laravel: драйверы и Horizon

Из коробки и документации Laravel ожидаемо встречаются:

  • sync — без очереди (для разработки и отладки).
  • database — таблица jobs, не требует Redis; хороша для малых нагрузок и простого деплоя, болезненна при большом числе воркеров и частых poll.
  • redis — стандарт для продакшена средней сложности; Horizon для мониторинга и конфигурации пулов.
  • sqs — облачный вариант без своего Redis.
  • RabbitMQ — через сообщество-пакеты, конфигурация exchange/queue.

failed_jobs, retry, timeout, число попыток — общие темы независимо от брокера: продумывайте идемпотентность обработчика, иначе retry удвоит побочные эффекты.


Другие фреймворки и экосистемы

  • Symfony Messenger — абстракция транспортов: AMQP, Redis, Doctrine, внешние адаптеры; удобно для CQRS-подобных схем и явных message-классов.
  • Django / Celery — классика Redis или RabbitMQ как брокер; богатая экосистема периодических задач.
  • Node.jsBull/BullMQ на Redis, amqplib для Rabbit; часто один Redis на всё приложение.
  • Java / SpringRabbitTemplate, KafkaListener, JMS; зрелая интеграция с брокерами в энтерпрайзе.
  • .NETMassTransit, Azure Service Bus, клиенты Confluent для Kafka.

Общий знаменатель: один и тот же Rabbit или Kafka может обслуживать несколько языков; договоритесь о формате сообщений (JSON, Avro, Protobuf) и версионировании схем.


Когда выбор — избыточен

Ситуация Часто достаточно Избыточно
Мало трафика, один сервер database или sync + cron Kafka-кластер «на вырост»
Фоновые письма и отчёты Redis + Horizon Отдельный Rabbit без межсервисной нужды
Один монолит на PHP Redis Распределённый лог + пять консьюмеров на других языках без причины
Огромный поток событий, много читателей Kafka или managed-аналог Одна Redis-list «на всё» без мониторинга

Избыточность — не только железо, но и когнитивная нагрузка: on-call должен понимать backlog, DLQ, rebalancing, lag.


Нюансы: доставка, порядок, яд

  1. Exactly-once в распределённой системе редко бывает бесплатным; чаще проектируют at-least-once + идемпотентные обработчики.
  2. Порядок в Kafka — внутри партиции; глобальный порядок по системе — отдельная задача.
  3. Poison message — сообщение, которое всегда падает; нужны лимит попыток, DLQ, алерты и ручной разбор.
  4. Мониторинг: длина очереди, lag консьюмеров, возраст oldest message, ошибки воркеров — без этого вы узнаёте о проблеме от пользователей.
  5. Версии сообщений: смена полей JSON без совместимости ломает старых консьюмеров.

Итог практичный: начните с честного ответа — вам нужна отложенная задача или общий журнал событий? От этого Redis, Rabbit или Kafka перестают быть «модным выбором» и становятся подходящим инструментом. Соседний материал про потоки событий и OLTP/OLAP хорошо дополняет эту тему с стороны данных, а гайд по Sail и очередям — с стороны локального стенда.