Redis: какую структуру данных выбрать для каждой задачи
В Redis важнее не сходство данных с объектами приложения, а нужные операции: быстрый поиск, очередь, уникальность или порядок по счёту. Разбираем, где подходят строки, хеши, списки, множества, sorted sets и Streams — и чем оборачивается неверный выбор.

В Redis выбор структуры данных определяет, какие операции будут простыми и быстрыми, а какие потребуют обходов, дополнительной логики или переезда на другой тип. Ниже — практическая шпаргалка по строкам, хешам, спискам, множествам, sorted sets и Streams на примерах для Redis Open Source 7.4: выбирайте структуру по запросам приложения, а не по тому, как данные выглядят в коде.
Сначала опишите операции, а не объект
Один и тот же «пользователь» можно сохранить строкой с сериализованным JSON или хешем. Если приложение всегда читает и обновляет профиль целиком, строка может быть удобнее. Если оно часто меняет отдельные поля, например тариф или имя, хеш позволяет обращаться к ним по отдельности.
Перед выбором ответьте на три вопроса: нужны ли выборки по частям, важен ли порядок элементов и должны ли элементы быть уникальными? Для потока событий добавьте четвёртый: нужно ли читать их последовательно нескольким потребителям. Эти ответы обычно сразу отсекают неподходящие типы.
Выбирайте структуру не под форму данных, а под самые частые операции над ними. Redis не превращает любую запись в удобную базу с произвольными запросами.
Шесть типов и их рабочие сценарии
| Тип | Когда брать | Цена и ограничение |
|---|---|---|
| Строка (String) | Кэш, счётчик, флаг, значение целиком | Для изменения поля внутри JSON придётся читать и записывать всё значение или отдельно разбирать его в приложении |
| Хеш (Hash) | Набор полей одной записи, которые читают или меняют по отдельности | Не даёт поиска по произвольному значению поля: хеш — не таблица с индексами |
| Список (List) | Последовательность с добавлением и снятием элементов с концов | Поиск произвольного элемента и удаление из середины обычно не подходят для горячего пути |
| Множество (Set) | Уникальные элементы, проверка членства, пересечение или объединение групп | Порядок не задан; для сортировки по числу нужен другой тип |
| Упорядоченное множество (Sorted Set) | Рейтинг, очередь с приоритетом, элементы со счётом и выдача по диапазону | Каждому элементу нужен числовой score; обновление счёта меняет его позицию |
| Поток (Stream) | Последовательность событий, которую читают один или несколько потребителей | Нужно отдельно продумать группы потребителей, подтверждения обработки и ограничение длины |
Строка. Это базовый выбор для значения, которое приложение получает и заменяет целиком: например, ключа кэша или простого флага. Строки также подходят для счётчиков с командами увеличения. Если вы сохраняете JSON как строку, не рассчитывайте на операции над его вложенными полями обычными командами String.
Хеш. Подходит для записи с несколькими полями, когда нужны выборочное чтение и обновление. Но нельзя спросить «найди все профили с тарифом pro» одной операцией над хешем: Redis не строит по полям хеша произвольные индексы. Если такие выборки важны, храните индекс отдельно или используйте систему, рассчитанную на запросы по полям.
Список. Выбирайте его, когда существенна последовательность и вы добавляете или забираете элементы с краёв. Например, LPUSH добавляет элемент в начало, а RPOP снимает с конца: вместе это даёт простую FIFO-очередь. Но наличие списка само по себе не решает повторную доставку, подтверждение обработки и восстановление зависших задач.
Set и Sorted Set. В Set каждый элемент уникален, поэтому структура удобна для набора участников или списка уже обработанных идентификаторов. Sorted Set хранит уникальные элементы со score и выдаёт их по позиции или диапазону score — полезно для рейтинга. Если порядок не нужен, не платите сложностью за Sorted Set; если нужен счёт, Set его не заменит.
Stream. Это вариант для событий, которые важно читать в порядке добавления и распределять между потребителями. У Stream есть идентификаторы записей и группы потребителей. Это не готовая гарантия «каждое событие обработано ровно один раз»: приложению нужны подтверждение обработки и логика разбора сообщений, оставшихся неподтверждёнными.
Команды для быстрой проверки выбора
Примеры рассчитаны на Redis Open Source 7.4 и запускаются в redis-cli, подключённом к вашему экземпляру. Они демонстрируют разные типы; команды создают ключи с указанными именами.
SET cache:page:42 "published"
HSET user:42 name "Mira" plan "pro"
LPUSH queue:email "job-101"
RPOP queue:email
SADD article:42:readers "user-7"
ZADD leaderboard 1250 "user-7"
ZREVRANGE leaderboard 0 9 WITHSCORES
XADD orders:events * type paid order_id 42
Здесь строка хранит одно значение, а хеш — два изменяемых поля профиля. Пара LPUSH и RPOP добавляет и забирает задачи по принципу FIFO; SADD не создаст второй такой же идентификатор в множестве. В Sorted Set команда ZREVRANGE возвращает участников от большего score к меньшему. XADD добавляет запись в Stream, а звёздочка просит Redis назначить ей идентификатор.
Перед запуском на рабочем окружении замените демонстрационные ключи на свои. Если команды отвечают ошибкой, проверьте подключение, права пользователя и версию сервера; у облачного Redis-сервиса набор доступных команд и правила доступа могут отличаться.
Когда что выбирать
- Нужно получить или заменить значение целиком — начните со строки.
- Нужно часто читать и менять поля одной записи отдельно — используйте хеш, если не требуется поиск по произвольным полям.
- Нужна очередь с операциями на концах — рассмотрите список; нужны группы потребителей и история событий — Stream.
- Нужна уникальность или проверка членства — Set; уникальность вместе с сортировкой по числу — Sorted Set.
Если типы кажутся одинаково подходящими, сравните реальные запросы: сколько элементов приложение читает за раз, как часто обновляет их и нужен ли порядок. Отдельно проверьте стоимость хранения на вашем объёме данных: универсальной цифры «сколько памяти занимает запись» нет, она зависит от данных и конфигурации Redis.
Что чаще всего ломается
- JSON в строке используют как базу с фильтрами. Получение значения работает, но выборка по вложенным полям превращается в дополнительную логику. Пересмотрите модель, если такие запросы стали регулярными.
- Из списка ждут надёжной очереди. Если потребитель забрал элемент и упал до обработки, простая схема на списке не обеспечивает подтверждение и возврат задачи. Для требований к доставке спроектируйте обработку ошибок отдельно или рассмотрите Stream с группой потребителей.
- Вместо множества выбирают упорядоченное множество «на всякий случай». Так появляется score и поддержка сортировки, которые могут быть не нужны. Если порядок не используется, Set проще по смыслу.
- В Stream не ограничивают рост и не следят за неподтверждёнными записями. Определите политику хранения событий и проверяйте состояние обработки: иначе ключ может расти, а сообщения — оставаться необработанными.
Score — числовое значение, по которому Redis упорядочивает элементы Sorted Set. Это может быть рейтинг, время или приоритет, но Redis не знает их смысл: его задаёт приложение.
Что проверить после выбора
Сначала соберите небольшой набор ключей на тестовом окружении и прогоните те же операции, которые будут в приложении: чтение, обновление, добавление и удаление. Затем проверьте объём памяти и поведение при росте данных, политику срока жизни ключей и восстановление после ошибки потребителя. Для Streams отдельно настройте обработку неподтверждённых событий, для очередей — сценарий повторной доставки. Инвалидация кэша и настройка персистентности Redis — отдельные темы; здесь мы сравнивали структуры по операциям.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: Redis documentation: Data types, Redis documentation: Commands
Частые вопросы
Можно ли хранить объект целиком как JSON-строку?
Чем Redis List отличается от Stream для очереди?
Что выбрать для рейтинга пользователей?
Будут ли примеры работать в другой версии Redis?
Нужно ли задавать срок жизни отдельно каждому элементу хеша или списка?
Хватит ли Stream, чтобы события не терялись?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.