Практический гайд по использованию Redis Streams (по состоянию на 2026) для построения event-driven backend. Примерные шаги можно выполнить за 45–90 минут на машине с 2 ГБ ОЗУ.
Статья была полезной?
XADD и XREAD.XGROUP и XREADGROUP.XACK, работа с pending list и повторная обработка.XINFO и XPENDING.6379.redis:7 (сжатый размер ~32 MB, распакованный ~60 MB, запуск контейнера ~200–500 ms).Redis Streams — встроенный в Redis тип данных, появившийся в Redis 5 и активно развиваемый в ветке 7.x. По состоянию на 2026 Streams остаются легковесным вариантом для реализации event-driven архитектур, где важна низкая задержка, простота деплоя и оперативная обработка сообщений. Streams хорошо подходят для уведомлений, очередей задач, синхронизации между сервисами и временных логов с коротким временем хранения.
Главные преимущества: простота настройки (Redis single binary, порт 6379), низкая латентность (<1 ms в локальной сети), и встроенные primitives для consumer groups, ack и повторной доставки. Ограничения: хранение в памяти (хотя есть опции виртуализации), отсутствие нативной партиционизации как у Kafka и модели длительного хранения больших объемов данных. В статье представлены практические команды и типовые ошибки, которые вы встретите при переходе к event-driven модели на Redis Streams.
Цель: научиться записывать события в stream и читать их простым способом. Команды приведены для redis-cli и Docker-окружения.
Команда (запись события):
redis-cli XADD mystream * event_type login user_id 42 timestamp 2026-03-01T12:00:00ZОбъяснение: XADD добавляет запись в stream mystream. Символ * просит Redis сгенерировать ID на основе текущего времени. Поля передаются как пары ключ/значение: event_type, user_id, timestamp.
Ожидаемый успешный вывод (пример):
"1710000000000-0"Пояснение вывода: ID формата UNIX-milliseconds-seq. В примере ID начинается с миллисекунд; значение будет отличаться в вашем окружении (время выполнения ~ <1 ms).
Типичная ошибка и как её фиксить:
(error) ERR wrong number of arguments for 'xadd' commandПричина: нечетное количество аргументов после ключа; поля должны идти парами ключ/значение. Фикс: проверить команду и добавить/удалить поле, чтобы пары соответствовали.
Чтение событий (негрупповое):
redis-cli XREAD COUNT 10 STREAMS mystream 0Объяснение: XREAD читает новые элементы. Параметр COUNT ограничивает число возвращаемых записей. Последний аргумент 0 означает чтение от начала стрима; для чтения только новых событий используйте $.
Ожидаемый вывод (пример):
1) 1) "mystream"
2) 1) 1) "1710000000000-0"
2) 1) "event_type"
2) "login"
3) "user_id"
4) "42"
5) "timestamp"
6) "2026-03-01T12:00:00Z"Типичная ошибка и фикс:
(nil)Причина: пустой ответ — нет данных в выбранном диапазоне. Фикс: проверьте правильность ID (вместо 0 используйте - для диапазона) или используйте XREAD BLOCK 1000 STREAMS mystream $ для блокирующего ожидания новых событий.

Скриншот вывода redis-cli после XADD и XREAD
Цель: создать consumer group и прочитать события несколькими потребителями параллельно, используя XGROUP и XREADGROUP.
Создание группы (если стрим отсутствует — флаг MKSTREAM создаст его):
redis-cli XGROUP CREATE mystream mygroup $ MKSTREAMОбъяснение: создаем группу mygroup для стрима mystream. Параметр $ означает, что группа начнет читать только новые сообщения, появившиеся после создания. MKSTREAM создаст stream, если его нет.
Ожидаемый вывод:
OKТипичная ошибка и фикс:
(error) BUSYGROUP Consumer Group name already existsПричина: группа уже создана. Фикс: удалить группу командой XGROUP DESTROY mystream mygroup или использовать XGROUP SETID для изменения позиции.
Чтение из группы (пример для потребителя consumer-1):
redis-cli XREADGROUP GROUP mygroup consumer-1 COUNT 5 BLOCK 2000 STREAMS mystream >Объяснение: XREADGROUP читает сообщения от имени группы. Специальный ID > означает только новые сообщения, назначенные группе впервые. BLOCK 2000 ставит таймаут 2000 ms на ожидание.
Ожидаемый успешный вывод:
1) 1) "mystream"
2) 1) 1) "1710000001234-0"
2) 1) "event_type"
2) "login"
3) "user_id"
4) "43"
5) "timestamp"
6) "2026-03-01T12:05:00Z"Типичная ошибка и фикс:
(error) NOGROUP No such key 'mystream' or consumer group 'mygroup'Причина: либо стрим отсутствует, либо группа не создана. Фикс: проверить существование стрима (EXISTS mystream) и создать группу с MKSTREAM.

Скриншот команды XGROUP и списка потребителей через XINFO
Цель: изучить подтверждения обработки сообщений, управление pending list и повторную доставку.
Подтверждение обработанного сообщения:
redis-cli XACK mystream mygroup 1710000001234-0Объяснение: XACK удаляет ID из pending list группы. Возвращает количество подтвержденных сообщений.
Ожидаемый вывод (пример):
(integer) 1Типичная ошибка и фикс:
(integer) 0Причина: возвращено 0 — указанный ID не найден в pending list для группы. Фикс: убедитесь, что ID корректен и принадлежал группе. Смотрите список незавершенных через XPENDING и повторно назначайте с помощью XCLAIM при необходимости.
Просмотр pending list и статистики:
redis-cli XPENDING mystream mygroup
redis-cli XINFO GROUPS mystream
redis-cli XINFO CONSUMERS mystream mygroupПримеры ожидаемого вывода:
1) (integer) 5 # общее число сообщений в PEL (pending entries list)
2) "1710000001000-0"
3) "1710000002000-0"
4) 1) 1) "consumer-1"
2) (integer) 3
3) (integer) 0
4) (integer) 0Повторная обработка несделанных сообщений (XCLAIM):
redis-cli XCLAIM mystream mygroup new-consumer 60000 1710000001000-0 IDLE 3600000Объяснение: XCLAIM позволяет перекласть владение над сообщением другому потребителю; параметр в миллисекундах задает минимальное время простоя (IDLE), после которого можно забирать сообщение. Use-case: consumer упал, нужно вернуть задания в работу.
Типичная ошибка и фикc:
(error) ERR No such consumerПричина: указанный consumer отсутствует. Фикс: создать consumer через чтение XREADGROUP или использовать корректное имя consumer в XCLAIM.
Цель: контролировать размер стрима, чтобы не переполнять память Redis. Покажем параметры XTRIM и MAXLEN.
Команда для мягкого ограничения длины (approximate trimming):
redis-cli XTRIM mystream MAXLEN ~ 10000Объяснение: MAXLEN ~ N оставляет около N последних записей, используя быстрый approximate алгоритм. Тильда (~) делает операцию быстрее, но менее точной. Выполнение команды обычно занимает миллисекунды, зависящее от объема удаляемых записей.
Ожидаемый вывод:
(integer) 9500Пояснение: возвращает число удалённых записей (примерное значение). Уточнение: точное число зависит от операций и состояния памяти.
Строгое ограничение (медленнее, точное):
redis-cli XTRIM mystream MAXLEN = 10000Ошибка и фикс:
(error) ERR syntax errorПричина: синтаксическая ошибка в использовании аргументов. Фикс: проверьте порядок аргументов и используйте либо ~, либо =, либо без модификаторов.
Советы по размерам: на 1 запись с 3 полями по 64 байта средний расход ОЗУ ~ 1 KB. Значит 10k записей ≈ 10 MB. На production задавайте лимиты с запасом и мониторьте used_memory в Redis INFO.
Цель: научиться получать ключевую телеметрию по streams и группам, находить «зависшие» сообщения и измерять задержки.
Команды для диагностики:
redis-cli XINFO STREAM mystream
redis-cli XINFO GROUPS mystream
redis-cli XPENDING mystream mygroup
redis-cli XRANGE mystream - + COUNT 10Ожидаемый вывод (фрагменты):
1) "length"
2) (integer) 12345
3) "first-entry"
4) 1) "1710000000000-0"
2) 1) "event_type"
2) "login"
...
# XPENDING summary
1) (integer) 12 # total pending
2) "1710000001000-0"
3) "1710000002000-0"
4) 1) 1) "consumer-1"
2) (integer) 6Типичная проблема: растущая очередь pending (XPENDING показывает много записей) и низкая скорость XACK. Причины: потребители тормозят, long processing, deadlock или GC в runtime. Фикс: масштабируйте число потребителей, увеличьте parallelism, профилируйте обработчик и используйте XCLAIM для восстановления заданий.
Метрики и SLA: измеряйте время от генерации события до XACK. Цель для real-time уведомлений — p50 < 50 ms, p95 < 200 ms в локальной сети; в облаке и при нагрузке значения будут выше. Для фоновых задач допустим p95 до нескольких секунд.
Сравнение основных характеристик по состоянию на 2026, с цифрами для практического выбора:
Коротко: используйте Redis Streams для low-latency, простых event-driven задач (уведомления, синхронизация, очереди задач), Kafka — для больших потоков данных, длительного хранения и сложной обработки в масштабах нескольких дата-центров.
Выбор между Redis Streams и альтернативами зависит от требований к задержке, объёму хранения и устойчивости:
XTRIM. Минимальная инфраструктура: один экземпляр Redis или кластер; рекомендуемые ресурсы для production: 4 GB ОЗУ и 2 vCPU для средней нагрузки.Exactly-once не реализуется «из коробки» в Redis Streams так же, как в Kafka с транзакциями. Достичь эффекта exactly-once можно комбинацией idempotent-обработки на уровне приложения, хранения состояния результата обработки (например в PostgreSQL с уникальным ключом по event_id) и аккуратного использования XACK только после коммита результата. Типовой паттерн: consumer читает событие, проверяет, не обработано ли оно (lookup по event_id), выполняет обработку и только после успешного коммита делает XACK. При рестарте consumers используют XPENDING и XCLAIM для восстановления непотверждённых задач.
Первое — настроить trimming: XTRIM с MAXLEN или периодическая агрегация старых событий в внешнее хранилище (S3/диск/Kafka). Мониторьте used_memory в INFO и установите алерты. Если требуется долговременное хранение больших объёмов, держите Redis как буфер/обработчик и экспортируйте архивы событий в Kafka или object storage. Для production учитывайте настройку vm.overcommit и AOF configuration, чтобы избежать нестабильности при нехватке памяти.
Redis Streams хранит позицию чтения внутри consumer group — это удобно, потому что оффсеты управляются на стороне Redis и доступны всем потребителям группы. Если вы строите кастомный механизм, можно хранить позицию в приложении или в базе данных для специфических сценариев восстановления. Для стандартных сценариев используйте встроенные consumer groups: это упрощает failover, XINFO и XPENDING дают готовую телеметрию.
Теоретически число потребителей в группе не ограничено, но практическая эффективность зависит от нагрузки и объема сообщений. Для небольших стримов десятки потребителей работают нормально. При сотнях потребителей начинаются накладные расходы на coordination и PEL. Если нужно масштабировать — используйте несколько групп или шардируйте стримы по ключам (например, user_id % N). Всегда мониторьте метрики: задержки, размер pending list и throughput.
Streams сохраняют ID, поддерживают чтение по диапазонам, consumer groups и pending list для надёжной доставки. LPUSH/RPOP — простая очередь без групп и без трекинга подтверждений. Для конкурентных обработчиков и гарантий повторной доставки Streams предпочтительнее. LPUSH/RPOP подойдут для простых FIFO очередей с быстрым потреблением, но без продвинутого управления отказами.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…