Когда внутри проекта нужно организовать обмен сообщениями, Redis предлагает сразу два подхода с разной философией и набором гарантий. Важно понять не только синтаксис команд, но и сценарии, где один механизм работает естественно, а другой окажется опухшим или небезопасным.

Ниже я разберу концепции, сильные и слабые стороны каждой схемы и приведу практические советы, основанные на реальных задачах из моей практики.

Что такое Pub/Sub и Streams в Redis

Pub/Sub — это модель публикации и подписки: отправитель публикует сообщение в канал, а все активные подписчики, слушающие этот канал, немедленно получают данные. Здесь нет хранилища сообщений — если подписчика нет в момент публикации, сообщение теряется.

Streams — это встроенная структура данных для упорядоченной записи событий, похожая на лог. Сообщения сохраняются с уникальными идентификаторами и могут быть потреблены группами потребителей с контролем смещений, подтверждений и повторной доставкой.

Pub/Sub: простота и низкая задержка

Pub/Sub привлекает минимализмом: одна команда PUBLISH — и сообщение тут же распространяется всем слушателям. Для задач с живыми обновлениями интерфейса или оповещений это удобный и быстрый путь.

Одна из главных сильных сторон — очень низкая задержка. В сценариях, где важна моментальная доставка и потеря отдельных сообщений допустима, Pub/Sub выглядит естественно.

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

Streams: надежность и контроль над потоком событий

Streams — это уже не просто транзит сообщений, а журнал событий с возможностью чтения произвольных сегментов. Сообщения сохраняются до явного удаления, что позволяет потребителям догонять поток и обрабатывать события в удобный момент.

Наличие consumer groups даёт механизмы распределения работы, подтверждений и повторной обработки: сообщения можно считать подтверждёнными только после успешной обработки. Это превращает Redis в легковесную очередь с устойчивыми гарантиями доставки.

Недостатки связаны с ответственностью за хранение: количество и размер сообщений влияют на объём памяти, а значит — на стоимость и требования к инстансу Redis. Для долгого хранения больших потоков придётся дополнительно думать про ротацию и архивирование.

Ключевые различия в одном взгляде

Чтобы принять решение, полезно сопоставить характеристики обоих подходов по практическим параметрам: гарантия доставки, хранение, масштабирование и сложность внедрения.

Параметр Pub/Sub Streams
Хранение сообщений Нет Да, до удаления
Гарантия доставки Нет (best-effort) Подтверждение и повторная доставка
Масштабирование потребителей Подписчики получают копии, сложность масштабирования на уровне сети Consumer groups позволяют распределять нагрузку
Подходит для Мгновенные оповещения, вещание Очереди задач, логи событий, аналитика

Когда стоит выбрать Pub/Sub

Выбирайте Pub/Sub, если потеря отдельных сообщений не критична, а первоочередная цель — минимальная задержка и простота реализации. Примеры: обновление позиции на карте в реальном времени, чат-комнаты, быстрые нотификации.

Pub/Sub удобно там, где количество одновременно подключённых клиентов невелико или инфраструктура размещена в пределах одного датацентра с низкой латентностью. В распределённых системах с сетевыми проколами потеря соединения будет означать потерю сообщений.

Когда стоит выбрать Streams

Streams оправдан, когда важны надёжность и возможность повторной обработки. Если сообщения нельзя терять — например, при обработке платежей, логировании событий или задачах фоновой обработки — выбор очевиден.

Streams удобен для построения конвейеров: разные группы потребителей могут параллельно обрабатывать одно и то же окно событий, каждый в своём темпе. Это делает структуру подходящей для аналитики и интеграций.

Производительность и масштабирование

Pub/Sub лучше при чистом вещании: при небольших объёмах канал передаёт сообщения без задержек. Но при росте числа подписчиков нагрузка на сеть и CPU сервера увеличивается пропорционально количеству клиентов.

Streams же более контролируем: потребители читают и подтвержают сообщения партиями. При корректной настройке consumer groups можно масштабировать обработку горизонтально, однако стоит учитывать требования к памяти и потокам записи.

Гарантии доставки и обработка ошибок

Pub/Sub не предоставляет механизма подтверждения: сообщение либо доставлено, либо нет. В случаях сетевых разрывов или падения подписчика восстановить пропущенные сообщения невозможно без сторонних решений.

Streams позволяют реализовать retry-паттерны: не подтверждённые сообщения остаются в pending list, администратор или отдельный воркер может их переназначить и повторно отправить на обработку. Это критично для задач с требованием «не потерять ничего».

Практические паттерны использования

Ниже несколько распространённых архитектурных приёмов, проверенных на реальных проектах.

  • Pub/Sub для UI-уведомлений: клиент подписывается на канал обновлений и получает события в реальном времени.
  • Streams для очередей задач: рабочие группы читают сообщения, подтверждают обработку и при сбое получают невыполненные элементы.
  • Комбинация: Pub/Sub оповещает о появлении новых записей в Stream, а потребители затем считывают и обрабатывают их надежно.

Комбинированный подход часто экономичен: быстрые уведомления идут через Pub/Sub, а критичные данные дублируются в Streams для гарантированного хранения и повторной обработки.

Пример из практики

Один из проектов, где я работал, использовал Pub/Sub для распространения событий пользовательского интерфейса. Это позволило сделать чаты и доски задач отзывчивыми при небольшой нагрузке.

Со временем требования выросли: понадобилось надёжно хранить сообщения и повторно обрабатывать задачи после падений воркеров. Мы добавили Streams для критичных процессов и организовали перекрёстные оповещения — Pub/Sub для скорости, Streams для надёжности. Это снизило потерю задач и улучшило мониторинг.

Советы по внедрению

Ниже несколько практических рекомендаций, которые помогают избежать распространённых ошибок при выборе и реализации.

  • Оцените критичность потери сообщений. Если допустима потеря — Pub/Sub упрощает архитектуру.
  • Планируйте очистку Stream: хранение бесконечных логов быстро съест память.
  • Используйте consumer groups для горизонтального масштабирования обработки в Streams.
  • Мониторьте длину pending list и задержки чтения — это индикатор проблем с потребителями.
  • При использовании Pub/Sub продумывайте поведение при переподключении клиентов и используйте механизмы републикации важных событий, если нужно.

Как выбрать в конкретном проекте

Вопрос выбора сводится к паре простых критериев: нужны ли вам гарантии и история, и сколько клиентов будет одновременно потреблять данные. Если важна история и повторная обработка — Streams. Если важна простота и мгновенная доставка для множества клиентов — Pub/Sub.

Прежде чем менять инфраструктуру, проведите нагрузочное тестирование на типичных сценариях: симулируйте пиковые нагрузки, падения клиентов и мердж потоков. Это быстрее покажет узкие места, чем теоретические обсуждения.

В любом случае ценность Redis — гибкость. Он позволяет начать с простого Pub/Sub и при росте требований плавно добавить Streams или комбинировать оба механизма, не ломая архитектуру полностью. Главное — определить требования к надежности, объёму хранимых данных и уровню сложности обработки, а дальше выбрать инструмент, соответствующий этим требованиям.