Гайды

Основы Redis: кеширование и структуры данных

Строки, хеши, списки, множества, sorted sets, cache-aside, eviction, TTL и типичные ошибки в продакшене.

~10 мин чтения

Основы Redis: кеширование и структуры данных

Redis — хранилище структур данных в памяти с моделью «ключ → значение» и примитивами: списки, множества, sorted sets, хеши, потоки и др. Чаще всего его используют как кеш, простые очереди, сессии и rate limiting. Pub/Sub и очереди на Lists подробнее — в гайде Redis Pub/Sub и очереди через Lists.


1. Архитектура: что держать в голове

  • В классической модели один поток команд — долгие команды блокируют остальные; KEYS в проде — антипаттерн.
  • Всё в RAM — при исчерпании памяти срабатывают maxmemory и eviction (или OOM).
  • Durability опциональна: RDB (снимки), AOF (журнал команд) — компромисс скорость / потеря последних секунд.
  • Горизонтальное масштабирование — Redis Cluster или шардирование на уровне приложения.

2. Установка и redis-cli

bash
docker run -d --name redis -p 6379:6379 redis:7-alpine

redis-cli -h 127.0.0.1 -p 6379 ping
# PONG

В redis.conf: bind, requirepass или ACL (ACL SETUSER), maxmemory, maxmemory-policy.


3. Строки (String)

redis
SET user:1001:name "Alice"
GET user:1001:name

SET counter:views:post-9 0
INCR counter:views:post-9
INCRBY counter:views:post-9 10

SET session:abc token-value EX 3600

EX / PX / EXAT — TTL или абсолютное время. MGET / MSET — меньше round-trip.


4. Хеши (Hash)

redis
HSET user:1001 name "Alice" email "a@example.com" plan "pro"
HGET user:1001 email
HGETALL user:1001
HINCRBY user:1001 logins 1

Меньше ключей в keyspace, чем плоский user:1001:email; TTL на весь объект проще.


5. Списки (List)

redis
LPUSH jobs:pending "task-1" "task-2"
RPOP jobs:pending
LLEN jobs:pending
LRANGE jobs:pending 0 -1

BRPOP — блокирующее чтение. Паттерны очередей — в отдельном гайде.


6. Set и Sorted Set

Set:

redis
SADD tags:post:9 redis database
SISMEMBER tags:post:9 redis
SMEMBERS tags:post:9

Sorted set (score + member):

redis
ZADD leaderboard 9800 "player:1"
ZADD leaderboard 10200 "player:2"
ZREVRANGE leaderboard 0 9 WITHSCORES
ZRANK leaderboard "player:1"

Удобно для топ-N и отложенных задач по score = время (ZRANGEBYSCORE).


7. Bitmap и HyperLogLog (кратко)

  • Bitmaps (SETBIT / GETBIT) — компактные флаги; следите за размером keyspace.
  • HyperLogLog (PFADD / PFCOUNT) — оценка кардинальности с погрешностью и малой памятью.

8. Кеш: cache-aside

  1. Читать Redis.
  2. При miss — БД, положить в Redis с TTL.
  3. При записи в БД — обновить или инвалидировать ключ.

Cache stampede: много промахов одновременно → все в БД. Лечение: singleflight, вероятностный ранний refresh TTL, SET nx на пересчёт.

Вероятностные структуры (модуль RedisBloom: Bloom / Cuckoo) удобны для «точно нет / возможно да» перед дорогим запросом в БД. Client-side caching (CLIENT TRACKING) в Redis 6+ снижает сетевой round-trip для горячих ключей — полезно вместе с библиотекой, поддерживающей invalidation.


9. Политики eviction (maxmemory-policy)

ПолитикаПоведение
noevictionОшибка на запись при полной памяти
allkeys-lruLRU среди всех ключей
volatile-lruСреди ключей с TTL
allkeys-lfu / volatile-lfuПо частоте (Redis 4+)

10. Транзакции и pipeline

MULTIEXEC — атомарный блок команд (не SQL-транзакция с откатом по ошибке внутри блока — модель Redis своя).

Pipeline в клиенте — пакетирование без ожидания ответа на каждую команду → ниже latency.


11. Прод: безопасность

  • Не открывайте 6379 в интернет без TLS, ACL и firewall.
  • Разделение по сервисам — префиксы ключей и дисциплина, не замена изоляции.
  • Persistence + backup для данных, которые нельзя потерять при рестарте.
  • Мониторинг: INFO, latency, экспортеры Prometheus.

12. Типичные ошибки

ОшибкаЭффект
KEYS * в продеБлокировка, всплеск latency
Нет TTL на кешРост памяти до eviction/OOM
Огромные JSON без сжатияRAM и сеть
Redis как единственная БД без AOF/RDBПотеря данных
Один инстанс без репликиSPOF

13. SCAN вместо KEYS

Для админских задач и миграций префикса используйте SCAN cursor MATCH pattern COUNT hint — итерация без блокировки всего keyspace, как у KEYS. В redis-py: for key in client.scan_iter(match="cache:user:*", count=500): .... На кластере SCAN идёт по одному шарду за раз; для полного обхода нужны обходы по мастерам слотов или согласованный дизайн ключей.


См. также