Типы Redis: string, hash, list, set, zset, TTL

О лекции

Redis — структуры данных в памяти с TTL на ключе. Выбор типа задаёт сложность команд и паттерн доступа, а не «просто кэш строк с JSON».

Кэш и Redis redis собеседование

Redis — структуры данных в памяти. Ключ — строка. Значение — один из типов. Команда на ключе атомарна. Исторически это однопоточный исполнитель: тяжёлая команда на большом ключе блокирует сервер для всех. Отдельные I/O-потоки в новых версиях не отменяют модель: вы по-прежнему не должны делать KEYS * и не должны хранить миллион полей в одном hash, если потом делаете HGETALL.

TTL висит на ключе целиком: EXPIRE, SET … EX, SET … PX. Истёк ключ — исчез целиком, не «одно поле хеша». Персистентность (RDB/AOF) и реплика — отдельная политика. Без неё Redis не место для денег, которые нельзя потерять.

Пример. Сессия session:abc с EX 1800. Через 30 минут ключ пропадает целиком. У хеша user:42 отдельного TTL на поле email в обычном Redis нет: живёт весь ключ или ничего.

Тип выбирают под операцию. Счётчик и сессия — string. Карточка пользователя с точечными полями — hash. Очередь — list. Уникальность и теги — set. Лидерборд и отложенные задачи по времени — zset. Если всё класть JSON в string, вы платите за сериализацию всего документа, даже когда нужно одно поле.

Какой тип для какой задачи

  • string — блобы, JSON целиком, счётчики INCR, SET NX как простой лок, сессии с TTL.
  • hash — объект с полями: HGET user:1 email без таскания всего JSON. HGETALL на огромном хеше — уже риск.
  • list — очередь LPUSH/RPOP, лента. Индекс в середине — O(n).
  • set — уникальность, пересечения, онлайн-присутствующие, теги.
  • zset — член плюс score: лидерборды, delayed queue по timestamp, «последние N по времени».

Сложность команды нужно называть. GET/SET — O(1) от размера значения, но скопировать 10 МБ JSON всё равно дорого. LINDEX в середине большого списка — O(n). ZRANGEBYSCORE зависит от размера выборки. «Redis быстрый» не отменяет большого ключа.

SET session:abc "{\"uid\":42}" EX 1800
HSET user:42 email a@b.c name Ann
ZADD feed:42 1710000000 post:9
ZADD delayed 1710000500 job:88
ZRANGEBYSCORE delayed 0 1710000000 LIMIT 0 50

Сессия строкой с TTL, карточка пользователя хешем, отложенная очередь — zset по timestamp.

Для delayed queue консьюмер читает диапазон score ≤ now, обрабатывает, ZREM — и должен быть идемпотентным, потому что крэш возможен между чтением и удалением.

Типичная ошибка

Один гигантский ключ: hash на миллион полей, список на миллионы элементов, JSON на десятки мегабайт. Команда блокирует сервер. KEYS * в проде — тот же класс беды. Нет схемы ключей: опечатка даёт вечный miss, который вы принимаете за «кэш не работает». TTL не продлили — «пропала сессия», хотя бизнес думал, что Redis надёжное хранилище профилей.

На собеседовании

Для каждого типа назовите одну-две команды и сложность. Объясните, почему TTL висит на ключе, а не на поле hash. Спросите себя, зачем тащить большой документ одним GET, если нужно одно поле — часто ответ hash, а не string.