Когда внутри проекта нужно организовать обмен сообщениями, 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 или комбинировать оба механизма, не ломая архитектуру полностью. Главное — определить требования к надежности, объёму хранимых данных и уровню сложности обработки, а дальше выбрать инструмент, соответствующий этим требованиям.

