Технологии и Инфраструктура → Redis: in-memory-решения
Redis: in-memory-решения
1) Где Redis уместен
Redis — высокоскоростное in-memory хранилище ключ-значение с богатыми структурами данных. Типичные сценарии:- Кеш (read-through/aside, TTL, SWR) и сессии.
- Счетчики и квоты: rate limiting, антифрод, лимиты кампаний.
- Лидерборды/рейтинги (ZSet), рекомендации «топ-N».
- Очереди/шины событий (Streams/PubSub), outbox/inbox, ретраи.
- Идемпотентность (ключи с TTL), de-dup вебхуков.
- Geo (поиск ближайших точек), Bitmap (флаги, DAU).
- Псевдонимы/токены и короткоживущие кэши авторизации.
2) Структуры данных и когда их применять
String: значения/счетчики (`INCRBY`), идемпотентные ключи.
Hash: агрегаты профилей/конфигов, хранение «легковесных» объектов.
List: простые очереди (но без replay/offset-семантики).
Set: уникальные элементы, дедупликация.
ZSet: сортировка по скору (лидерборды, TTL-календарь — «отложенные» события).
Stream: устойчивые очереди c потребительскими группами, `XREADGROUP`/replay — для вебхуков, CDC, ретраев.
Geo: `GEOADD/GEORADIUS` — ближайшие точки/мерчантов.
Bitmap/Bitfield: серии флагов (логины по дням, DAU/WAU).
HyperLogLog: приблизительные уникальные (UU) дешево по памяти.
Bloom/Cuckoo (модули): быстрые проверки наличия, снижают «MISS» к источнику.
- RedisJSON (JSON документы), RediSearch (индексация/поиск), RedisBloom (вероятностные структуры), TimeSeries (метрики/агрегации).
3) Ключи, TTL и политики памяти
Нейминг и сегментация:
tenant:{t}:domain:{d}:{entity}:{id}:v{schema} region={R} currency={C} lang={L}
Версионируйте (`vN`), включайте только значимые измерения (регион/валюта/язык/тенант).
Изолируйте пространства ключей per-tenant.
- Используйте TTL-матрицу (сек/мин/час), добавляйте джиттер (±10–20%) чтобы избегать stampede.
- Для горячих ключей — refresh-ahead и single-flight (один лидер обновляет).
- `allkeys-lru/lfu` — общий кеш без TTL-зависимости.
- `volatile-lru/lfu` — только ключи с TTL.
- `noeviction` — отказ записи при переполнении (безопаснее для критичных очередей/счетчиков).
- Подбирать под сценарий и всегда мониторить `evicted_keys`.
4) Транзакции, пайплайны и скрипты
Пайплайны: снижают RTT, группируйте 10–100 команд.
Транзакции (MULTI/EXEC): не изолируют чтения, но атомарно выполняют пакет.
Optimistic locking: `WATCH key` → проверка → `MULTI/EXEC`.
Lua-скрипты: атомарная логика на стороне сервера (rate limit, locks, composite-операции).
5) Очереди и шины: List vs Stream
List + `BRPOP` — просто, но нет consumer groups, offset/replay, слабая устойчивость к падениям.
Stream: `XADD → XREADGROUP → XACK`, retry-deadletter (невзятые за N минут), партиционирование по ключу. Рекомендуется для вебхуков PSP/KYC, отложенных выплат/уведомлений.
Приоритетные очереди: несколько стримов по приоритетам, потребители «высасывают» из высокого в первую очередь.
Отложенные задачи: ZSet где score=timestamp; периодический `ZRANGEBYSCORE` ≤ now → перенос в Stream.
6) Высокая доступность и масштабирование
Репликация: master→replica (read-scale).
Sentinel: автоматический failover master’а, обнаружение, клиентские URI.
Redis Cluster: шардирование на 16384 слота, горизонтальный scale-out. Ключи, использующие несколько структур, заверните в хэш-теги `{order:123}`.
- Для кеша/сессий — кластер/реплики, `client-side hashing` поддержан SDK.
- Для очередей/стримов — минимизируйте кросс-слотовые операции; партиционируйте по ключам домена.
7) Персистентность: RDB, AOF и бэкапы
RDB (снимки): быстрее, экономнее; риск потери последних секунд/минут.
AOF (журнал): меньше потерь; режимы `everysec/always`. Сжатие AOF и периодическая переупаковка.
Гибрид: RDB + AOF → быстрое восстановление + умеренные потери.
Бэкапы: снапшоты и копии AOF в объектное хранилище; проверяйте восстановление регулярно.
Для критичных очередей/идемпотентности выбирайте AOF `everysec` + репликацию.
8) Безопасность и комплаенс
AUTH/ACL: роли per-приложение, запрет «опасных» команд (`FLUSHALL`, `KEYS`).
TLS на клиент-сервер и межузловых линках; фиксированные egress-IP.
Сегментация сети: приватные подсети, SG/NACL; доступ только из нужных сервисов/неймспейсов.
Секреты не логируйте; PAN/PII в Redis — только токены/деривативы.
Команды ключей: избегайте `KEYS ` — используйте `SCAN`.
9) Наблюдаемость и SLO
Ключевые метрики:- Latency (P95/P99), `instantaneous_ops_per_sec`, `connected_clients`.
- Hit ratio, evicted_keys, expired_keys.
- Memory: used, fragmentation ratio, RSS, allocator stats.
- Replication lag, AOF/RDB частоты и размеры, fork time.
- Streams: PEL (pending entries list), delivery latency, retry count.
- Операции Redis P99 ≤ 5–10 мс.
- Evictions ≤ 1%/час (кеш-пространства).
- Stream delivery P99 ≤ 500 мс, retry rate < 2%.
10) FinOps и планирование ресурсов
Память дорога: измеряйте $/GB-мес RAM vs экономия запросов к origin/БД.
Включайте компрессию значений >1–2 КБ (смотрите на CPU).
LFU может дать лучший hit при меньшем объеме.
Для изображений/больших блобов — не Redis: используйте CDN+объектное хранилище.
11) Паттерны для iGaming/финтех
11.1 Rate limiting (скользящее окно, Lua)
Идея: `INCRBY` в ключе окна + TTL; Lua атомарно проверяет лимит и увеличивает.
lua
-- KEYS[1]=key ARGV[1]=limit ARGV[2]=ttlSec ARGV[3]=inc local cur = redis. call('INCRBY', KEYS[1], ARGV[3])
if cur == tonumber(ARGV[3]) then redis. call('EXPIRE', KEYS[1], ARGV[2]) end if cur > tonumber(ARGV[1]) then return {0, cur} else return {1, cur} end
11.2 Идемпотентность запросов
Ключ `idemp:{request_id}` с TTL 24h, значение — результат/статус. Перед выполнением операции — проверяем наличие.
11.3 Лидерборды
`ZINCRBY leaderboard:game:{g} score user:{u}` → `ZREVRANGE... WITHSCORES`.
Для топ-N по региону/тенанту — отдельные ZSet или префиксы.
11.4 Очередь вебхуков PSP
`XADD psp:webhooks...` → группы потребителей `XGROUP CREATE psp:webhooks g1 $`.
Ретраи «зависших» сообщений через PEL-сканирование (`XPENDING` → `XCLAIM`).
11.5 Отложенные выплаты
ZSet `payout:due` (score=epoch) → воркер периодически переносит готовые элементы в Stream `payout:exec` с дедупликацией.
11.6 Антифрод-счетчики
Комбинация `PFADD` (уникальные) + `INCR` (интенсивность) + гео/ASN-метки; триггеры для ручной проверки.
12) Работа с памятью и производительностью
Пулы соединений клиентов; уменьшайте RTT (keep-alive).
Предпочитайте пайплайны к пачке команд.
Следите за big keys (`MEMORY USAGE`, `SCAN`) — лучше дробить объекты.
Hash c малым числом полей экономичнее многих отдельных ключей.
Включайте io-threads (read-heavy), если профит подтвержден тестами.
Избегайте частых `FLUSHDB/ALL` в проде; управляйте через префиксы и `UNLINK` для безопасного удаления.
13) Мульти-тенант и изоляция
Отдельные кластера/инстансы или logical DB per-tenant (если нагрузка мала).
Квоты на ключи/память, раздельные ACL.
Префиксы в ключах и метрики по namespace.
14) Locking и согласованность
SET key val NX PX=ttl — простой mutex.
Redlock: используйте аккуратно; для распределенных критичных транзакций лучше опираться на «источник истины» (БД/ledger) и идемпотентные операции.
Предпочитайте атомарные операции и Lua вместо «долгих» блокировок.
15) Анти-паттерны
Хранение больших блобов/изображений — перегруз RAM и сетей.
Финансовые инварианты (баланс) только в Redis.
`KEYS ` и «сканирование мира» в проде.
Отсутствие TTL/джиттера — dogpile на истечении.
Политика `allkeys-` на критичных очередях → потеря данных при давлениях.
Смешивание очередей, кеша и сессий в одном инстансе без квот и приоритетов.
Lua-скрипты, работающие по ключам разных слотов в Cluster.
16) Чек-лист внедрения
1. Определите роли: кеш/сессии, очереди/стримы, счетчики/лимиты — разнесите по инстансам/кластерам.
2. Выберите maxmemory-policy под задачу; задайте лимиты и мониторинг evictions.
3. Нейминг ключей, версии схем, TTL-матрица + джиттер; single-flight для топ-ключей.
4. Для очередей — Streams (группы, ретраи, DLQ), для отложенных — ZSet + перенос.
5. HA: репликация + Sentinel или Redis Cluster; проверьте failover клиента.
6. Персистентность: RDB/AOF под сценарий; регулярные бэкапы и тест восстановления.
7. Безопасность: ACL, TLS, частные сети, запрет опасных команд.
8. Наблюдаемость: latency, ops/sec, memory, evictions, replication lag, stream PEL.
9. FinOps: профили памяти, крупные ключи, компрессия, LFU; избегайте Redis для больших блобов.
10. Документация паттернов (rate-limit, идемпотентность, лидерборды) и тесты нагрузок.
Итог
Redis — это «многофункциональный швейцарский нож» скорости: кеш, очереди, счетчики, лидерборды, гео и вероятностные структуры. Его сила — в правильном выборе структур данных, дисциплине TTL/инвалидации, атомарности операций, а также в продуманной HA/персистентности и наблюдаемости. Используйте Redis там, где важны миллисекунды и высокий RPS, при этом оставляя критичные инварианты (деньги, учет) «источнику истины» — так платформа останется и быстрой, и надежной.