Модуль 26

Redis як кеш: стратегії кешування

Ось готовий урок, створений за твоїм майстер-промптом. Пристебни паски, ми починаємо! 🚀


🎓 Тема: Redis як кеш: стратегії кешування

Привіт, друзі! Радий бачити вас усіх тут. 👋

Сьогодні ми не просто вивчаємо "ще одну базу даних". Сьогодні ми говоримо про швидкість. Ми говоримо про те, як змусити ваш додаток літати, а не повзти, коли на нього зайдуть тисячі користувачів.


1. 🔥 Вступ: Чому ваш додаток «гальмує»?

Уявіть ситуацію. Ви запустили стартап — інтернет-магазин кросівок. «Чорна п’ятниця». Тисячі людей одночасно заходять на головну сторінку, щоб побачити топ-5 популярних моделей.

Кожен захід користувача — це запит до вашої основної бази даних (наприклад, PostgreSQL або MySQL). База даних каже: "Окей, я піду на диск, знайду таблицю, відфільтрую замовлення, порахую популярність, відсортую і віддам результат".

Це займає, скажімо, 200 мілісекунд. Небагато, так? А тепер помножте це на 10 000 користувачів. Ваша база даних починає диміти, сервер падає, клієнти йдуть до конкурентів. 📉

Питання до вас: Чи є сенс 10 000 разів перераховувати одне й те саме, якщо топ кросівок не змінюється щосекунди?

Звісно, ні!

Ось тут на сцену виходить Redis. Уявіть, що ваша основна база даних (PostgreSQL) — це величезна бібліотека в підвалі. Щоб знайти книгу, треба спуститися, знайти полицю, взяти книгу і піднятися. Це довго.

А Redis — це стіл бібліотекаря прямо біля входу. Найпопулярніші книги лежать прямо на столі. Ви запитуєте — і отримуєте відповідь миттєво. Без підвалів. Без пошуків.

Без кешування сучасний веб просто не вижив би.


2. 🧠 Теоретична база (Що під капотом?)

Що таке Redis у контексті кешу? Це сховище типу Key-Value (Ключ-Значення), яке живе в оперативній пам’яті (RAM).

Як це працює?

  • RAM vs Disk: Доступ до оперативної пам’яті в тисячі разів швидший, ніж до жорсткого диска.
  • Структура: Це просто гігантська хеш-таблиця (як dict у Python або об'єкт у JS). Ви даєте ключ (product:123), Redis миттєво віддає дані.

Три поняття, які треба запам'ятати (обов'язково!):

  1. TTL (Time To Live) — "Час життя". Дані в кеші не повинні жити вічно. Вони протухають. Ми ставимо таймер (наприклад, 5 хвилин), після якого дані зникають. Чому? Щоб не показувати користувачу ціну, яка змінилася вчора.
  2. Cache Hit (Влучання) — Ми запитали кеш, і дані там були. Супер, ми зекономили час!
  3. Cache Miss (Промах) — Ми запитали кеш, а даних там немає (або час TTL вийшов). Доведеться йти в "підвал" (основну БД).

Головна стратегія: Cache-Aside (Ліниве завантаження)

Це найпопулярніший підхід. Логіка проста, як двері: 1. Додаток запитує дані у Redis. 2. Якщо є (Hit) → повертаємо клієнту. 3. Якщо немає (Miss) → йдемо в БД, беремо дані, записуємо їх у Redis і віддаємо клієнту.

Інтуїтивно: Це як шпаргалка на іспиті. Спершу дивишся в шпаргалку. Якщо там нема відповіді — напружуєш мозок (БД), пишеш відповідь і дописуєш її в шпаргалку на майбутнє.


3. 🧪 Приклади (Код у студію!)

Давайте подивимось на псевдокод (схожий на Python), щоб зрозуміти суть.

Приклад 1: Найпростіший (Без стратегії)

# Просто запис і читання
redis.set("hello", "world")
print(redis.get("hello")) 
# Виведе: "world"

Нудно, правда? Це ми і так знали.

Приклад 2: Реальний сценарій (User Profile)

Уявіть функцію, яка віддає профіль користувача.

Питання: Що станеться, якщо ми не знайдемо користувача в кеші?

def get_user_profile(user_id):
    cache_key = f"user:{user_id}"

    # 1. Стукаємо в Redis
    data = redis.get(cache_key)

    if data:
        print("⚡️ Взяли з кешу!")
        return json.loads(data)

    # 2. Якщо промахнулися (Miss) — йдемо в БД
    print("🐌 Йдемо в повільну БД...")
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)

    # 3. Записуємо в Redis на майбутнє (з TTL 60 секунд)
    redis.setex(cache_key, 60, json.dumps(user))

    return user

Чому результат саме такий? Перший раз виклик буде повільним (йдемо в БД). Але наступні 60 секунд цей user_id буде віддаватися миттєво. Навантаження на базу падає в рази!

Приклад 3: Проблема (Інвалідація)

А що, якщо користувач змінив аватарку? В базі вона нова, а в Redis ще 50 секунд буде стара. Це називається Stale Data (Застарілі дані).

Рішення: Коли ми оновлюємо дані, ми повинні вбити кеш.

def update_user_profile(user_id, new_data):
    # 1. Оновлюємо основну БД
    db.execute("UPDATE users SET ...", new_data)

    # 2. ВИДАЛЯЄМО старий запис з кешу
    redis.delete(f"user:{user_id}")

    print("♻️ Дані оновлено, кеш очищено!")

Наступного разу get_user_profile не знайде даних у Redis, піде в БД і затягне вже нову версію. Елегантно, чи не так?


4. 🛠 Практична частина

Тепер ваша черга. Не бійтеся помилятися — саме так ми вчимося.

Завдання 1: Основи Напишіть код (можна на листочку або в голові), який зберігає в Redis курс долара "41.50" з ключем usd_rate, але так, щоб він зник рівно через 10 секунд.

Завдання 2: Логіка Cache-Aside У вас є функція get_product_price(product_id). Допишіть пропущені кроки: 1. Перевірити кеш. 2. ... (що тут?) 3. Якщо кешу немає: отримати ціну з БД. 4. ... (що тут зробити перед поверненням?)

Завдання 3: Міні-кейс "Лічильник переглядів" Ми хочемо рахувати перегляди сторінки. Писати в БД (+1) на кожен клік — це вбивство бази. Як використати Redis, щоб збирати кліки швидко, а в базу писати, скажімо, раз на хвилину? (Підказка: команда INCR).

Завдання 4: А що, якщо... Що станеться з вашим кодом із Прикладу 2, якщо Redis раптово вимкнеться (впаде сервер)? * А) Весь сайт впаде з помилкою 500. * Б) Сайт працюватиме, але повільно. * В) Користувачі побачать старі дані. (Подумайте, як обробити ConnectionError).


5. 💡 Мислення як у розробника

Ось де відрізняється новачок від профі.

Помилка новачка: Кешувати все підряд. "Закешуємо весь список користувачів!" Ні! Пам'ять Redis дорога і не гумова. Кешуйте те, що часто читають, але рідко змінюють (Top products, User session, Configs).

Думка профі: "Є тільки дві складні речі в Computer Science: інвалідація кешу та неймінг змінних". (Філ Карлтон). Найскладніше — не записати дані в Redis, а знати, коли їх звідти видалити.

Порада з практики: Завжди ставте TTL. Завжди. Навіть якщо ви думаєте, що дані вічні. Якщо ви не поставите TTL, ваш Redis перетвориться на смітник із даними 5-річної давності, і сервер впаде від нестачі пам'яті (OOM — Out Of Memory).


6. 🧩 Підсумок

Отже, що ми маємо в сухому залишку?

  1. Redis — це наша "оперативна пам'ять" для вебу. Швидка, як блискавка. ⚡️
  2. Стратегія Cache-Aside — спочатку дивись у Redis, потім у БД. Це стандарт індустрії.
  3. TTL — наш найкращий друг, щоб дані не протухали і пам'ять не закінчувалась.

Тепер ви вмієте не просто писати запити, а оптимізувати навантаження. Ви знаєте, як врятувати базу даних від смерті у "Чорну п'ятницю".

Що далі? Ми навчилися зберігати дані. Але Redis вміє дещо крутіше... Уявіть, що один сервіс хоче миттєво сказати іншому: "Гей, надійшло нове замовлення, відправ SMS!". На наступному уроці ми поговоримо про Redis Pub/Sub та черги повідомлень. Це буде справжня магія асинхронності!

А поки що — удачі з кодом! 💻