Redis vs MongoDB: битва кэша и документов в стиле Mortal Kombat

redis vs mongodb

Введение: Турнир, достойный легенд

Представьте арену, где два бойца — Redis и MongoDB — сошлись в эпической схватке. Один — мастер блицкрига, другой — повелитель структуры. Мы не будем раздавать медали, а разберем, кому и когда отдавать предпочтение. В этой статье:

  • Подробные технические сравнения.
  • Реальные кейсы и примеры кода.
  • Советы по интеграции, безопасности и масштабированию.
  • Ответ на вопрос: «А что, если использовать их вместе?».

Готовы? Let’s go!

Раунд 1: Скорость — Когда каждая миллисекунда на счету

Redis: Пуля, которая не знает промаха

Архитектура в двух словах:

  • In-memory хранение: Все данные живут в RAM.
  • Однопоточность: Нет накладных расходов на блокировки.
  • Протокол RESP: Бинарно-текстовый формат для минимизации оверхеда.

Где это блестит:

  1. Кэширование: Сессии пользователей, HTML-страницы, результаты сложных вычислений.
  2. Счетчики: Лайки, просмотры, активность в реальном времени.
  3. Очереди: Отправка email, обработка задач в фоне (через Redis Streams или Lists).

Что там по числам? ну хоть приблизительно:

  • Чтение/запись: 100,000+ операций в секунду.
  • Кэширование: Подходит для сессий, токенов, топ-10 котиков дня.
  • Задержка: 0.1 мс (пока MongoDB только зашнуровывает кроссовки).

Пример (Go): Топ-10 игроков в реальном времени


// Добавляем очки игрока в сортированный набор
client.ZAdd("leaderboard", &redis.Z{
    Score: player.Score,
    Member: player.ID,
})

// Получаем топ-10
topPlayers, err := client.ZRevRangeWithScores("leaderboard", 0, 9).Result()

Ловушки Redis:

  • Потеря данных при падении: Если не настроена персистентность (RDB/AOF), данные исчезнут.
  • Ограничение по RAM: 100 ГБ данных? Придется шардировать или покупать сервер с памятью как у NASA.

MongoDB: Тяжелая артиллерия для сложных миссий

Архитектура в двух словах:

  • Документ-ориентированность: JSON-like BSON + гибкая схема.
  • WiredTiger Storage Engine: Кэширование в RAM + сжатие данных на диске.
  • Оптимизация для записи: Журналирование (write-ahead logging) для надежности.

Где это блестит:

  1. Каталоги товаров: Вложенные атрибуты, фильтры по 20 параметрам.
  2. Контент-платформы: Блоги, комментарии, теги.
  3. Аналитика: Агрегации по терабайтам данных.

Пример (MongoDB): Поиск товаров с пагинацией

db.products.find({
    category: "электроника",
    price: { $lt: 1000 },
    "specs.ram": { $gte: 8 }
})
.skip(20)
.limit(10)
.sort({ price: -1 }); 

Ловушки MongoDB:

  • Нет JOIN: Придется денормализировать данные или использовать $lookup (но это не то же самое).
  • Требования к диску: SSD обязательно, иначе запросы будут грустить.

Раунд 2: Гибкость данных — Битва форматов

Redis: Строгий учитель, который любит порядок

Типы данных Redis:

  1. Строки: Текст, JSON, сериализованные объекты.
  2. Хеши: Поля-значения (например, профиль пользователя).
  3. Списки: Очереди (LPUSH, RPOP).
  4. Сеты: Уникальные значения (подписки, теги).
  5. Сортированные наборы: Рейтинги, топы.

Пример: Кэширование API-ответов в Redis (Go)


// Проверяем кэш перед запросом к БД
cachedData, err := client.Get("api:products:latest").Result()

if err == nil {
    return json.Unmarshal([]byte(cachedData), &products)
}

// Если кэша нет — запрашиваем БД и сохраняем
products = fetchFromDB()
jsonData, _ := json.Marshal(products)
client.Set("api:products:latest", jsonData, 10*time.Minute)

Проблема: Redis не умеет вложенные запросы. Хотите найти всех пользователей из Москвы? Придется хранить отдельный набор «users:moskow».

MongoDB: Свободный художник с JSON-кистями

Фичи, от которых разработчики плачут от счастья:

  1. Индексы: Составные, текстовые, геопространственные.
  2. Агрегации: Конвейеры для сложной аналитики.
  3. Транзакции: Поддержка ACID в кластере (с версии 4.0+).

Пример: Агрегация для интернет-магазина

db.orders.aggregate([
    { $match: { date: { $gte: "2023-01-01" } } },
    { $unwind: "$items" },
    { $group: {
        _id: "$items.category",
        totalSales: { $sum: "$items.price" },
        count: { $sum: 1 }
    }},
    { $sort: { totalSales: -1 } }
]);
// Результат: продажи по категориям за 2023 год. 

Проблема: Если не настроить индексы, агрегации будут работать как улитка в сиропе.

Раунд 3: Масштабируемость — Кто вырастет до размеров Годзиллы?

Redis: Вертикальное vs горизонтальное

  • Вертикальное: Купить сервер с 1 ТБ RAM → просто, но дорого.
  • Горизонтальное: Redis Cluster (шардирование данных между узлами).

Как работает Redis Cluster:

  • Данные делятся на 16384 слота.
  • Каждый узел отвечает за диапазон слотов.
  • Клиент перенаправляет запросы на нужный узел.

Проблемы кластера:

  • Нет кросс-слотовых операций. Нельзя выполнить MGET по ключам из разных узлов.
  • Требует поддержки на уровне клиента (библиотеки должны уметь работать с кластером).

Пример настройки кластера (Docker):

# Запускаем 6 узлов (3 мастера, 3 реплики)
docker run -d --name redis-node1 redis redis-server --cluster-enabled yes
... # Повторить для node2-node6
# Собираем кластер
redis-cli --cluster create \
127.0.0.1:7001 127.0.0.1:7002 ... \
--cluster-replicas 1 

MongoDB: Шардирование как образ жизни

Архитектура кластера:

  • Шарды: Горизонтальное деление данных (например, по диапазону ID или хешу).
  • Конфиг-серверы: Хранят метаданные о распределении данных.
  • Маршрутизаторы (mongos): Перенаправляют запросы к нужному шарду.

Пример: Шардирование по локации пользователей

sh.shardCollection("mydb.users", { country: 1, city: 1 });
// Данные пользователей из одной страны группируются на одном шарде. 

Плюсы:

  • Автоматическое балансировка данных.
  • Запросы к одному шарду работают быстрее.

Минусы:

  • Сложность настройки.
  • Нужно заранее выбрать ключ шардирования (ошибка приведет к «горячим» шардам).

Раунд 4: Безопасность — Кто лучше защитит ваши данные?

Redis: Минимализм как проклятие

  • Аутентификация: Пароль через requirepass в конфиге.
  • Шифрование: Только через TLS (с версии 6.0).
  • Роли: Нет встроенной системы ролей (используйте внешние инструменты).

Совет: Не открывайте Redis в публичный доступ. Если пришлось — используйте VPN или Cloudflare Access.

MongoDB: Полный фарш безопасности

  • Аутентификация: SCRAM-SHA-1/256, x.509 сертификаты.
  • Роли: Гибкие права (например, «только чтение» или «админ БД»).
  • Шифрование: TLS, шифрование данных на диске (Enterprise версия).
  • Audit Log: Логирование всех операций (кто, что, когда).

Пример настройки ролей:

use admin
db.createRole({
    role: "dataReader",
    privileges: [{ resource: { db: "mydb", collection: "" }, actions: ["find"] }],
    roles: []
}) 

Раунд 5: Стоимость владения — За что придется платить?

Redis: Дешево, но рискованно

  • Самостоятельный хостинг:
    • Виртуалка с 4 ГБ RAM ≈ $20/мес.
    • Но если RAM закончится — данные потеряются.
  • Облачные решения:
    • AWS ElastiCache: от $0.022 за час (cache.t3.micro).
    • Redis Enterprise: $1.5/ГБ RAM в месяц.

MongoDB: Дорого, но предсказуемо

  • Самостоятельный хостинг:
    • Требует SSD и мощных CPU.
    • Виртуалка с 16 ГБ RAM + 100 ГБ SSD ≈ $80/мес.
  • Облачные решения:
    • MongoDB Atlas: от $57/мес (M10, 2 ГБ RAM, 10 ГБ SSD).
    • Бесплатный тариф: 512 МБ RAM (для тестов).

Раунд 6: Интеграция с экосистемой — Кто больше дружит с Docker и Kubernetes?

Redis: Легкий как пушинка

  • Docker: Официальный образ весит 45 МБ.
  • Kubernetes: StatefulSet + Persistent Volume для персистентности.
  • Helm-чарты:
    helm install redis bitnami/redis --set password=secret 

MongoDB: Тяжеловес, но с поддержкой

  • Docker: Официальный образ — 600 МБ.
  • Kubernetes:
    • Операторы (MongoDB Enterprise Operator) для автоматизации управления.
    • Шардирование через Helm.
  • Интеграция с Atlas: Развертывание кластера в облаке одной командой.

Финальный раунд: Когда они объединяются

Сценарий: Социальная сеть с 1 млн пользователей

  • Redis:
    • Кэш ленты новостей.
    • Счетчики лайков/просмотров.
    • Очереди для отправки уведомлений.
  • MongoDB:
    • Основное хранилище постов, профилей, комментариев.
    • Агрегации для аналитики (топ авторов, активность по часам).

Пример архитектуры:

Клиент → Веб-сервер (Go)
    ↳ Redis (кэш, сессии)
    ↳ MongoDB (основные данные)
    ↳ Redis Streams (асинхронные задачи) 

Итог: Нокаута нет — есть правильный выбор

Выбирайте Redis, если:

  • Нужна скорость доступа к данным.
  • Данные временные (кэш, сессии).
  • Вы работаете с очередями или real-time analytics.

Выбирайте MongoDB, если:

  • Данные сложные и меняются часто.
  • Нужны сложные запросы и агрегации.
  • Масштабирование важно с первого дня.

И помните: они отлично дополняют друг друга. Как Рокки и Аполло — по отдельности сильны, вместе — непобедимы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *