Skip to content

Latest commit

 

History

History
467 lines (322 loc) · 17.6 KB

File metadata and controls

467 lines (322 loc) · 17.6 KB

Лекция 25. NoSQL. Куки, сессии, кеш

📚 Введение в NoSQL

NoSQL (от англ. Not Only SQL — «не только SQL») — это термин, обозначающий типы баз данных, отличные от традиционных реляционных СУБД. NoSQL БД предлагают более гибкие модели хранения данных и лучше подходят для масштабируемых распределённых систем.

Подробнее:


🧨 Почему NoSQL?

NoSQL БД появились как ответ на ограничения реляционных СУБД в условиях:

  • горизонтального масштабирования,
  • работы с большими объёмами неструктурированных или слабо структурированных данных,
  • необходимости высокой доступности и отказоустойчивости.

⚖️ Подробно о CAP-теореме

CAP-теорема (также называемая теоремой Брюера) гласит, что в распределённой системе невозможно одновременно обеспечить:

Свойство Описание
Consistency (Согласованность) Все узлы видят одинаковые данные в один и тот же момент.
Availability (Доступность) Система всегда отвечает на запрос (даже если это не последняя версия).
Partition Tolerance (Устойчивость к разделению) Система продолжает работать, даже если между узлами есть сетевые проблемы.

🧠 Зачем нужна CAP-теорема?
При проектировании распределённых систем (особенно в NoSQL) часто приходится жертвовать чем-то ради надёжности и масштабируемости. Например:

  • В случае сетевого разделения можно либо отказать в доступе (жертвуем A),
  • Либо отдать устаревшие данные (жертвуем C).

Вывод: система может выбрать максимум два из трёх свойств одновременно.

Примеры:

  • 🔸 Cassandra — AP: предпочитает доступность и устойчивость, согласованность достигается позже (eventual consistency).
  • 🔸 MongoDB (до 4.0) — CP: жертвует доступностью при проблемах с сетью.
  • 🔸 Redis (в кластере) — чаще AP.

🔢 Основные типы NoSQL баз данных


1. 🗝️ Key-Value (Ключ-значение)

Простейшая модель, напоминающая словарь: ключ → значение.

Пример хранения:

{
  "user:123": "Alice",
  "user:124": "Bob",
  "cart:456": {
    "item": "Book",
    "qty": 2
  }
}

Где используется:

  • Redis в GitHub — как брокер сообщений и кэш состояний пайплайнов.
  • DynamoDB в Amazon — хранение корзин и профилей пользователей.

2. 📄 Document-oriented (Документные БД)

Хранят данные в виде документов (JSON, BSON и т.д.).

Пример хранения:

{
  "_id": "user_001",
  "name": "Alice",
  "email": "alice@example.com",
  "orders": [
    {"item": "Book", "qty": 2},
    {"item": "Pen", "qty": 5}
  ]
}

Где используется:

  • MongoDB в eBay — данные пользователей и товаров.
  • CouchDB в BBC — автономный режим с синхронизацией.

3. 📊 Column-family (Колонночные БД)

Колонночные базы данных на первый взгляд похожи на реляционные, но различие — в физической организации хранения данных.

🆚 В чём отличие от реляционных БД?
Реляционные БД (PostgreSQL, MySQL) Колонночные БД (Cassandra, Bigtable)
Единица хранения строка (row) столбец (column) или «семейство столбцов»
Физическое хранение строки лежат вместе значения одного столбца лежат вместе
Сценарий оптимизации запись/чтение строк аналитика, агрегации по столбцам
Гибкость схемы строго задана допускаются разные наборы столбцов

Пример хранения (упрощённо):

RowKey: user1
  Name: Alice
  Age: 30
  City: Prague

RowKey: user2
  Name: Bob
  Age: 25

Где используется:

  • Cassandra в Netflix — логирование, телеметрия.
  • Bigtable в YouTube — просмотры, комментарии, рекомендации.

4. 🔗 Graph (Графовые БД)

Графовые базы данных хранят данные как узлы (nodes) и связи (edges) между ними.

Пример хранения:

(Alice)-[:FRIEND]->(Bob)
(Alice)-[:LISTENS_TO]->(Song)
(Alice)-[:VISITED]->(Place)
🧠 Почему графы так важны?

Механизм поиска связей между сущностями используется повсеместно:

  • Facebook: "Возможно, вы знаете этого человека" — через общих друзей.
  • Spotify: "Похожие исполнители" — через пользователей с похожими интересами.
  • Google Maps: построение маршрута — как поиск кратчайшего пути в графе дорог.

Все эти задачи решаются одними и теми же графовыми алгоритмами (DFS, BFS, Dijkstra и т.д.) на одних и тех же структурах — графах.

Где используется:

  • Neo4j в eBay — рекомендации и antifraud.
  • Amazon Neptune — персонализация и графы предпочтений.
  • LinkedIn — поиск и визуализация сетей профессиональных связей.

💡 Применение и сравнение

Сценарий Тип NoSQL Примеры
Кэш, сессии, временные данные Key-Value Redis, Memcached
Пользователи, CMS Document-oriented MongoDB, CouchDB
Аналитика, временные ряды Column-family Cassandra, Bigtable
Связи, рекомендации, маршруты Graph Neo4j, Neptune, OrientDB

🧾 Когда использовать NoSQL?

✅ Используй, если:

  • структура данных часто меняется или неформализована;
  • требуется масштабирование и отказоустойчивость;
  • важны скорость доступа и запись в real-time.

❌ Не подходит, если:

  • необходима строгая согласованность и транзакции;
  • бизнес-логика требует сложных JOIN-операций;
  • используется строго табличная модель с контролем схемы.

💬 Комментарий преподавателя:
Redis — универсальный инструмент. Он почти всегда есть в стеке. Даже если не используется на старте, его часто добавляют позже для кэширования, очередей и хранения сессий. Мы с ним ещё поработаем дальше по курсу.

🍪 Куки, 🧾 Сессии и ⚡ Кеширование в Django

HTTP-протокол не сохраняет состояния. Чтобы "помнить" пользователя, его действия и не делать одни и те же вычисления много раз — используются куки, сессии и кеш.


🧭 Что нужно понимать

  • HTTP stateless — каждый запрос сам по себе, без истории.
  • Cookie — способ сохранять небольшие данные на стороне клиента (браузера).
  • Session — способ сохранять пользовательские данные на сервере, привязанные к уникальному sessionid, передаваемому в Cookie.
  • Cache — быстрая память для хранения часто используемых данных (не обязательно связанных с пользователем).

🍪 Cookie (печеньки)

Куки — это пары ключ:значение, которые браузер хранит локально и отправляет на сервер с каждым HTTP-запросом к соответствующему домену.

Примеры применения:

  • Сохранение корзины товаров
  • Запоминание темы оформления
  • Предзаполнение форм
  • Авторизация через sessionid

Куки существуют только на уровне HTTP запроса! Их может запоминать браузер, но прямого отношения к серверу они не имеют!

🧾 Сессии

Сессия — это механизм сохранения информации между запросами одного и того же пользователя. Чаще всего для реализации сессий используется привязка к куки.

Как это работает в Django:

Браузер → POST /login → Сервер:
    - создаёт Session в БД
    - возвращает Set-Cookie: sessionid=<uuid>

Браузер → GET /profile → Cookie: sessionid → Сервер:
    - достаёт данные из request.session

Где хранятся данные:

  • По умолчанию — в таблице базы данных django_session
  • Также возможны:
    • Redis
    • Файлы
    • Signed cookies

🛠 Использование

# Работа с сессией в Django
request.session['visited'] = True

# Проверка
if request.session.get('visited'):
    ...

# Удаление
del request.session['visited']

💡 Пример — ограничение комментариев

def post_comment(request, comment):
    if request.session.get('has_commented', False):
        return HttpResponse("You've already commented.")
    request.session['has_commented'] = True
    return HttpResponse("Thanks!")

🧪 Пример — хранение временной метки

request.session['last_action'] = timezone.now()

🧩 Вне запроса (SessionStore)

from django.contrib.sessions.backends.db import SessionStore

s = SessionStore()
s['foo'] = 'bar'
s.create()
s.session_key  # сохранённый ключ

🛑 Важные нюансы

  • Ключи сериализуются в строки (JSON)
  • Данные сохраняются только при изменении request.session как объекта
request.session['foo'] = 'bar'  # сохранится
request.session['foo']['x'] = 1  # ❌ не сохранится

✅ Можно настроить:

SESSION_SAVE_EVERY_REQUEST = True

🧹 Очистка старых сессий

python manage.py clearsessions

Или вручную:

from django.contrib.sessions.models import Session

Session.objects.filter(...).delete()

⚡ Кеширование

Кеш — это временное хранилище для ускорения доступа к часто используемым данным.

💡 Пример

# Вместо:
Article.objects.filter(published=True).order_by('-date')[:5]

# Лучше:
articles = cache.get('homepage_articles')
if not articles:
    articles = Article.objects.filter(...).all()
    cache.set('homepage_articles', articles, timeout=3600)

📦 Варианты backends

Хранилище Плюсы Минусы
Redis Быстро, работает в памяти, масштабируется Требует установки и сервера
Memcached Очень быстрый, простой Только строковые ключи
FileBased Не требует серверов Медленный на больших объёмах
Database Ничего не нужно настраивать Нагрузка на БД
DummyCache Ничего не делает (для dev) Нет кеша :)

⚙️ Настройки кеша (пример Redis)

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient"
        }
    }
}

🎯 Использование

from django.core.cache import cache

cache.set("key", "value", timeout=60)
cache.get("key")  # "value"
cache.delete("key")

Массовые операции:

cache.set_many({"a": 1, "b": 2})
cache.get_many(["a", "b"])

🧱 Кеширование view

from django.views.decorators.cache import cache_page


@cache_page(60 * 15)
def my_view(request):
    ...

Или в urls.py:

path("foo/", cache_page(900)(views.foo_view))

🧰 Кеширование шаблонов

{% load cache %}
{% cache 300 sidebar %}
    ...HTML sidebar...
{% endcache %}

🧼 Очистка кеша

cache.clear()

⛔ Отключение кеша для отдельной view

from django.views.decorators.cache import never_cache


@never_cache
def dynamic_view(request):
    ...

📌 Итоги

  • Куки — данные на клиенте (браузере).
  • Сессии — данные на сервере, привязанные к пользователю.
  • Кеш — быстрая память для ускорения работы, не связана напрямую с пользователем.
  • Всё это критично для безопасной, быстрой и удобной работы сайта.

🧠 Вопросы для закрепления

  1. Чем отличаются куки от сессий?
  2. Почему сессии нельзя использовать для анонимных пользователей везде?
  3. Где по умолчанию Django хранит сессии?
  4. Что произойдёт, если модифицировать request.session['key']['value']?
  5. Как бы вы реализовали кеширование главной страницы?
  6. Как очистить все сессии, старше 30 дней?