Что такое кэш?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Кэш
Определение
Кэш (Cache) — это механизм для временного хранения часто используемых данных с целью повысить скорость доступа и снизить нагрузку на основное хранилище. Данные из кэша доступны быстрее, чем из источника.
Уровни кэширования
CPU Cache — встроенный в процессор кэш (L1, L2, L3)
Memory Cache — кэш в оперативной памяти (Redis, Memcached)
Disk Cache — кэш на диске (браузер, CDN)
Application Cache — кэш на уровне приложения (в памяти программы)
Стратегии кэширования
LRU (Least Recently Used) — удаляет давно не использованные данные
FIFO (First In First Out) — удаляет самые старые данные
LFU (Least Frequently Used) — удаляет редко используемые данные
Пример с Python
from functools import lru_cache
import requests
# Встроенный декоратор кэширования
@lru_cache(maxsize=128)
def expensive_function(n):
time.sleep(2)
return n ** 2
# Первый вызов — 2 секунды
print(expensive_function(5)) # 25
# Второй вызов — из кэша, мгновенно
print(expensive_function(5)) # 25
Кэширование HTTP запросов
import requests
from requests.adapters import HTTPAdapter
from cachecontrol import CacheControl
# Использование кэша для HTTP запросов
session = requests.Session()
cached_session = CacheControl(session)
response = cached_session.get("https://api.example.com/data")
# Следующий запрос будет из кэша
response = cached_session.get("https://api.example.com/data")
Redis кэш (в реальных приложениях)
import redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def get_user(user_id):
# Проверяем кэш
cached = redis_client.get(f"user:{user_id}")
if cached:
return json.loads(cached)
# Если нет в кэше, запрашиваем из БД
user = database.get_user(user_id)
# Сохраняем в кэш на 1 час
redis_client.setex(f"user:{user_id}", 3600, json.dumps(user))
return user
Кэширование в браузере
Браузер использует HTTP заголовки для кэширования:
- Cache-Control: max-age=3600 — кэшировать на 1 час
- Expires: дата — дата истечения кэша
- ETag — уникальный идентификатор версии
- Last-Modified — дата последнего изменения
Тестирование кэша
import pytest
from unittest.mock import patch, MagicMock
def test_cache_hit():
with patch('redis.Redis.get') as mock_get:
mock_get.return_value = '{"id": 1}'
result = get_user(1)
assert result["id"] == 1
mock_get.assert_called_once()
def test_cache_miss():
with patch('redis.Redis.get') as mock_get, \
patch('database.get_user') as mock_db:
mock_get.return_value = None
mock_db.return_value = {"id": 1}
result = get_user(1)
mock_get.assert_called()
mock_db.assert_called()
Инвалидация кэша
def update_user(user_id, data):
# Обновляем в БД
database.update_user(user_id, data)
# Инвалидируем кэш
redis_client.delete(f"user:{user_id}")
Преимущества кэша
- Улучшение производительности
- Снижение нагрузки на основное хранилище
- Уменьшение задержек сети
- Экономия ресурсов
Недостатки
- Проблемы с консистентностью данных
- Дополнительное потребление памяти
- Сложность инвалидации
Для QA важно тестировать: попадания в кэш, промахи, инвалидацию и консистентность данных.