Настройка Redis-кешування для бекенду мобільного додатка
Мобільний клієнт робить запит за лентою новин. Бекенд йде у PostgreSQL, виконує JOIN на трьох таблицях, застосовує фільтри, сортує — 200–400 мс. Користувач оновлює ленту — знову 200–400 мс, хоча дані не змінилися. Redis кешує результат цього запиту, і повторне звернення займає 1–5 мс. Різниця відчувається фізично.
Що кешувати, що ні
Хороші кандидати для Redis:
- Результати важких агрегуючих запитів (топ користувачів, статистика, каталог)
- Дані, які запитуються часто та мінливаються рідко (конфігурація програми, налаштування, довідники)
- Результати зовнішніх API-вызовів (геокодування, курси валют)
- Сесії та токени аутентифікації
Погані кандидати:
- Дані конкретного користувача, які мінливаються при кожній його дії
- Транзакційні дані (баланс рахунку, статус замовлення) — ризик показати застаріле стан
- Дані з коротким TTL та високою вартістю обчислення інвалідації
Архітектура кешування
Cache-Aside (Lazy Loading)
Найбільш поширений паттерн. Додаток спочатку перевіряє Redis, при промаху — йде у БД і записує результат у кеш.
def get_news_feed(user_id: int, page: int):
cache_key = f"feed:{user_id}:page:{page}"
cached = redis.get(cache_key)
if cached:
return json.loads(cached)
data = db.query_feed(user_id, page)
redis.setex(cache_key, 300, json.dumps(data)) # TTL 5 хвилин
return data
Мінус: перший запит після закінчення TTL або cold start завжди повільний. На високонавантажених API це може привести до thundering herd — сотні запитів одночасно промахиваються у кеш і йдуть у БД. Захист: mutex lock (через SET NX) або probabilistic early expiration.
Write-Through
При записі даних — одразу оновлюємо і БД, і кеш. Кеш завжди актуальний. Дорожче на запис, простіше на читання. Підходить для профілів користувачів, налаштувань.
Read-Through
Кеш сам знає, як завантажити дані при промаху. Реалізується через Redis modules або бібліотеки типу RedisOM. Для більшості мобільних бекендів надмірно.
Стратегія ключів та TTL
Структура ключів: {сервіс}:{сущність}:{id}:{варіант}. Приклад: app:feed:user:42:page:1, app:config:global:v2.
TTL підбирається під частоту змін:
- Конфігурація програми: 1–24 години
- Каталог товарів: 5–30 хвилин
- Лента новин: 1–5 хвилин
- Профіль користувача: 5–15 хвилин
Без TTL кеш росте до упору пам'яті. Redis при заповненні пам'яті з політикою allkeys-lru починає витісняти ключі — можна втратити важливі дані несподівано. Явний TTL надійніший.
Інвалідація
Найскладніша частина. Паттерни:
За подією: при оновленні профілю видаляємо app:profile:user:42:* через SCAN + DEL. Не використовуємо KEYS * у продакшені — це O(N) блокуюча операція.
Тегований кеш: кожному ключу додаємо теги в окремому set (SADD tag:user:42 "app:feed:user:42:page:1"). При інвалідації — беремо всі ключі тегу та видаляємо. Бібліотеки Cache-Tags реалізують це автоматично.
Версіонування: замість інвалідації — зміна версії у ключі (app:config:global:v3). Старий ключ просто закінчується по TTL.
Настройка Redis у продакшені
Мінімальні вимоги для мобільного бекенду:
-
maxmemoryявно обмежуємо (наприклад, 512 МБ) -
maxmemory-policy allkeys-lru— витіснення найменш використовуваних ключів при досягненні ліміту - Persistence: для кешу можна вимкнути (
save "") — при перезагрузці кеш пересоберіться - Sentinel або Redis Cluster для відмовостійкості у продакшені
Моніторинг: redis-cli INFO stats → keyspace_hits vs keyspace_misses. Hit rate нижче 80% — щось не так зі стратегією кешування. used_memory та evicted_keys — дивимось постійно.
Терміни: базова настройка Cache-Aside для основних ендпоїнтів — два-три робочих дні. Повна стратегія з інвалідацією та моніторингом — чотири-сім днів.







