Кэширование в JavaScript: Redis, Memcached и встроенные решения для Node.js

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Кэширование в JavaScript: Redis, Memcached и встроенные решения

Кэширование — одна из ключевых стратегий оптимизации производительности веб-приложений. В экосистеме JavaScript (особенно в Node.js) разработчики имеют доступ к мощным инструментам: от встроенных механизмов до распределённых систем вроде Redis и Memcached. В этой статье мы разберём, как и когда использовать каждый из подходов, с реальными примерами кода.

Зачем нужно кэширование в Node.js?

Без кэширования каждый запрос к серверу может приводить к дорогостоящим операциям: чтению из базы данных, сложным вычислениям или вызовам внешних API. Кэш сохраняет результат первого запроса и отдаёт его при повторных обращениях. Это снижает нагрузку на сервер, уменьшает время ответа и улучшает пользовательский опыт.

Основные сценарии использования кэша в Node.js:

  • Результаты запросов к базе данных (особенно агрегаций)
  • Ответы внешних API (погода, курсы валют)
  • Тяжёлые вычисления (генерация отчётов, обработка изображений)
  • Сессии пользователей и токены аутентификации

Встроенное кэширование в JavaScript (Node.js)

Простейший способ — использовать объект Map или Object для хранения данных в памяти процесса. Это быстро, но имеет ограничения: данные живут только пока работает сервер, и память не ограничена.

Пример: Кэш на Map с TTL (Time To Live)

class SimpleCache {
    constructor(ttl = 60000) {
        this.cache = new Map();
        this.ttl = ttl; // время жизни в мс (по умолчанию 1 минута)
    }

    set(key, value) {
        this.cache.set(key, {
            value,
            timestamp: Date.now()
        });
    }

    get(key) {
        const item = this.cache.get(key);
        if (!item) return null;
        if (Date.now() - item.timestamp > this.ttl) {
            this.cache.delete(key);
            return null;
        }
        return item.value;
    }

    delete(key) {
        this.cache.delete(key);
    }

    clear() {
        this.cache.clear();
    }
}

// Использование
const cache = new SimpleCache(30000); // 30 секунд
cache.set('user_123', { name: 'Иван', role: 'admin' });
const user = cache.get('user_123');
console.log(user); // { name: 'Иван', role: 'admin' }

Плюсы: нулевая задержка, простота, не требует внешних зависимостей.
Минусы: данные теряются при перезапуске, ограничены памятью одного процесса, не подходит для распределённых систем.

Для более продвинутого встроенного кэша можно использовать пакет node-cache, который добавляет автоматическую очистку, статистику и поддержку строковых ключей.

Redis: распределённый кэш для Node.js

Redis — это in-memory хранилище данных, которое часто используется как кэш. В Node.js для работы с Redis используется пакет ioredis (более современный, чем redis).

Установка и базовое подключение

npm install ioredis
const Redis = require('ioredis');
const redis = new Redis({
    host: 'localhost',
    port: 6379,
    // password: 'your-password' // если требуется
});

redis.on('connect', () => console.log('Подключено к Redis'));
redis.on('error', (err) => console.error('Redis ошибка:', err));

Пример: Кэширование данных с TTL

const Redis = require('ioredis');
const redis = new Redis();

async function getCachedData(key, fetchFunction, ttl = 3600) {
    // Пытаемся получить из кэша
    const cached = await redis.get(key);
    if (cached) {
        return JSON.parse(cached);
    }

    // Если нет — получаем данные и сохраняем
    const data = await fetchFunction();
    await redis.setex(key, ttl, JSON.stringify(data));
    return data;
}

// Пример использования: кэширование ответа API
async function fetchWeather(city) {
    const response = await fetch(`https://api.weather.com/${city}`);
    return response.json();
}

// Кэшируем на 5 минут (300 секунд)
const weather = await getCachedData('weather:moscow', () => fetchWeather('moscow'), 300);
console.log(weather);

Продвинутые возможности Redis

  • Структуры данных: хэши, списки, множества, сортированные множества
  • Pub/Sub: для уведомлений об инвалидации кэша
  • Lua-скрипты: атомарные операции с кэшем
  • Кластеризация: для горизонтального масштабирования

Плюсы: распределённый, быстрый, поддерживает сложные структуры, сохраняет данные при перезапуске (RDB/AOF).
Минусы: требует отдельного сервера, потребляет много оперативной памяти, сложнее в настройке.

Memcached: лёгкий и быстрый

Memcached — это специализированная система кэширования, проще Redis, но с меньшим функционалом. Для Node.js используется пакет memcached.

Установка и подключение

npm install memcached
const Memcached = require('memcached');
const memcached = new Memcached('localhost:11211');

memcached.on('issue', (details) => {
    console.error('Memcached проблема:', details);
});

Пример: Кэширование с Memcached

const Memcached = require('memcached');
const memcached = new Memcached('localhost:11211');

function cacheData(key, data, ttl = 3600) {
    return new Promise((resolve, reject) => {
        memcached.set(key, data, ttl, (err) => {
            if (err) reject(err);
            else resolve();
        });
    });
}

function getCached(key) {
    return new Promise((resolve, reject) => {
        memcached.get(key, (err, data) => {
            if (err) reject(err);
            else resolve(data || null);
        });
    });
}

// Использование
async function example() {
    await cacheData('session:user42', { id: 42, name: 'Анна' }, 1800);
    const session = await getCached('session:user42');
    console.log(session); // { id: 42, name: 'Анна' }
}


                
                

Блоги

Рекомендаций по книгам