Какие существуют два основных подхода к кэшированию данных?

«Какие существуют два основных подхода к кэшированию данных?» — вопрос из категории Архитектура, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Существует два фундаментальных подхода к реализации кэширования, различающихся местом хранения данных:

1. Кэширование в памяти (In-Memory Caching)

Данные хранятся непосредственно в оперативной памяти (RAM) приложения. Этот подход обеспечивает максимальную скорость доступа.

  • Преимущества:
    • Очень низкая задержка (latency), так как нет сетевых запросов.
    • Простота реализации для кэширования внутри одного процесса.
  • Недостатки:
    • Энергозависимость: кэш очищается при перезапуске или сбое приложения.
    • Масштабируемость: кэш ограничен объемом RAM одного сервера и недоступен для других экземпляров приложения.

Пример в Python (мемоизация): Декоратор functools.lru_cache кэширует результаты вызовов функции.

from functools import lru_cache
import time

@lru_cache(maxsize=128)
def expensive_calculation(n):
    """Имитация долгой операции"""
    time.sleep(1)
    return n * n

# Первый вызов займет 1 секунду
print(expensive_calculation(10))

# Второй вызов вернет результат из кэша мгновенно
print(expensive_calculation(10))

2. Внешнее кэширование (External/Distributed Caching)

Данные хранятся в отдельном, независимом сервисе (например, Redis, Memcached), к которому приложение обращается по сети.

  • Преимущества:
    • Персистентность: данные сохраняются между перезапусками приложения.
    • Масштабируемость: кэш может быть общим для множества экземпляров приложения или микросервисов.
    • Больший объем хранения, ограниченный только ресурсами кэш-сервера.
  • Недостатки:
    • Более высокая задержка из-за сетевых вызовов.
    • Требует развертывания и поддержки дополнительной инфраструктуры.

Пример в Python с Redis:

import redis

# Подключение к серверу Redis
r = redis.Redis(host='localhost', port=6379, db=0)

# Сохранение значения в кэш с временем жизни 60 секунд
r.set('user:1:profile', '{"name": "Alice"}', ex=60)

# Получение значения из кэша
cached_profile = r.get('user:1:profile')
if cached_profile:
    print(cached_profile.decode('utf-8'))