Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🟢
Intermediaire 20 min Node.js

Caching avec Node.js et Redis

Pourquoi Caching avec Node.js et Redis ?

Dans un environnement de développement moderne, l'optimisation des performances est cruciale pour maintenir une bonne expérience utilisateur. Le caching est une technique efficace qui permet d'améliorer la vitesse et l'efficacité d'une application en stockant les données les plus fréquemment utilisées dans la mémoire vive. Avec Node.js et Redis, on peut mettre en place un système de caching robuste et performant.

Un cas concret : Imaginez une application e-commerce avec des pages de produit qui sont souvent consultées. En utilisant le caching avec Redis, chaque fois qu'un utilisateur visite une page de produit, nous pouvons vérifier d'abord si les données sont déjà en cache. Si oui, on retourne directement les données depuis la mémoire, évitant ainsi un accès à la base de données et réduisant le temps de réponse.

Prerequis

Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :

  • Connaissances en Node.js
  • Installation de Node.js (v14 ou plus)
  • Installation de Redis (version 6.2 ou plus)

Vous pouvez installer Node.js via le site officiel nodejs.org et Redis via redis.io/download.

Concepts fondamentaux

What is Caching?

Le caching est la technique d'entreposage de données temporairement dans une zone de stockage rapide pour accélérer l'accès à ces données. Dans le contexte du développement web, cela signifie que les données populaires sont mises en cache afin qu'elles puissent être récupérées rapidement sans avoir besoin d'y accéder directement.

// Exemple simple de caching avec Node.js et Redis

const redis = require('redis');
const client = redis.createClient();

client.set('key', 'value', redis.print); // Mettre une valeur dans le cache
client.get('key', (err, reply) => {
  if (err) throw err;
  console.log(reply); // Affiche : value
});

Redis

Redis est un système de base de données en mémoire à haut débit et open source. Il est connu pour sa vitesse et sa simplicité. Dans ce tutoriel, nous allons utiliser Redis comme stockage de cache.

// Connexion à Redis avec Node.js

const redis = require('redis');
const client = redis.createClient();

client.on('error', (err) => {
  console.log(`Redis error: ${err}`);
});

Middleware

Le middleware est une fonction qui s'exécute entre la requête entrante et la réponse sortante dans un serveur web. Dans le contexte du caching, on peut utiliser des middlewares pour automatiser l'ajout de données en cache et leur récupération.

// Exemple de middleware de caching

const express = require('express');
const app = express();

app.use((req, res, next) => {
  const key = req.url;
  client.get(key, (err, reply) => {
    if (err) throw err;
    if (reply) {
      // Si la réponse est en cache, on la retourne directement
      res.send(reply);
    } else {
      // Sinon, on continue le traitement normal
      next();
    }
  });
});

app.get('/data', (req, res) => {
  // Simuler une opération coûteuse
  const data = 'large_data_here';
  client.set(req.url, data, redis.print);
  res.send(data);
});

app.listen(3000, () => console.log('Server running on port 3000'));

Mise en pratique : projet fil rouge

Projet : Un gestionnaire de tâches (Task Manager)

Dans ce mini-projet, nous allons créer un gestionnaire de tâches simple qui utilise le caching avec Redis pour stocker les tâches populaires.

Étape 1 : Initialisation du projet

mkdir task-manager
cd task-manager
npm init -y
npm install express redis body-parser

Étape 2 : Création des fichiers

Créez un fichier server.js et une structure de dossier comme suit :

task-manager/
├── models/
│   └── tasks.js
├── routes/
│   └── tasks.js
├── server.js
└── package.json

Étape 3 : Configuration du serveur

// server.js

const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

require('./routes/tasks')(app);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

Étape 4 : Modèle de données

// models/tasks.js

const redis = require('redis');
const client = redis.createClient();

module.exports = {
  getTasks: async (req, res) => {
    const key = '/tasks';
    client.get(key, async (err, reply) => {
      if (err) throw err;
      if (reply) {
        // Si les tâches sont en cache, on les retourne directement
        return res.send(JSON.parse(reply));
      } else {
        // Sinon, on récupère les tâches de la base de données et on les met en cache
        const tasks = await getTasksFromDB();
        client.set(key, JSON.stringify(tasks), redis.print);
        res.send(tasks);
      }
    });
  },
  addTask: async (req, res) => {
    const task = req.body;
    await addTaskToDB(task); // Ajouter la tâche à la base de données
    const tasks = await getTasksFromDB();
    client.set('/tasks', JSON.stringify(tasks), redis.print);
    res.send(task);
  }
};

Étape 5 : Gestion des routes

// routes/tasks.js

const express = require('express');
const router = express.Router();
const { getTasks, addTask } = require('../models/tasks');

router.get('/', async (req, res) => {
  await getTasks(req, res);
});

router.post('/', async (req, res) => {
  await addTask(req, res);
});

module.exports = router;

Étape 6 : Fonctions de base de données simulées

// Pour la simplicité, on utilise un tableau pour stocker les tâches

let tasks = [];

const getTasksFromDB = async () => {
  return new Promise((resolve) => {
    resolve(tasks);
  });
};

const addTaskToDB = async (task) => {
  return new Promise((resolve) => {
    tasks.push(task);
    resolve();
  });
};

Étape 7 : Test du projet

Exécutez le serveur avec la commande suivante :

node server.js

Accédez à http://localhost:3000/tasks dans votre navigateur pour voir les tâches. Ajoutez une tâche via une requête POST.

Autres fonctionnalités

  • Supprimer une tâche (DELETE /tasks/:id)
  • Mettre à jour une tâche (PUT /tasks/:id)

Erreurs frequentes et debugging

1. Erreur : La clé n'est pas trouvée dans le cache

// ❌ Mauvais
const key = req.url;
client.get(key, (err, reply) => {
  if (reply) {
    res.send(reply);
  } else {
    // Problème ici : on ne gère pas l'erreur correctement
  }
});

// ✅ Correct
const key = req.url;
client.get(key, (err, reply) => {
  if (err) throw err;
  if (!reply) {
    res.status(404).send('Task not found');
  } else {
    res.send(reply);
  }
});

2. Erreur : Connexion à Redis échoue

// ❌ Mauvais
const client = redis.createClient();

client.on('error', (err) => {
  console.log(`Redis error: ${err}`);
});

// ✅ Correct
const client = redis.createClient({
  url: 'redis://localhost:6379'
});

client.on('error', (err) => {
  console.log(`Redis error: ${err}`);
});

3. Erreur : Données non stockées en cache

// ❌ Mauvais
const key = req.url;
client.set(key, JSON.stringify(tasks), redis.print);

// ✅ Correct
const key = req.url;
client.set(key, JSON.stringify(tasks), (err) => {
  if (err) throw err;
});

Pour aller plus loin

1. Utilisation de Redis avec Express et Mongoose

Intégrez Redis avec Express pour stocker des modèles Mongoose en cache.

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const redis = require('redis');

const app = express();
app.use(bodyParser.json());

mongoose.connect('mongodb://localhost:27017/task-manager', { useNewUrlParser: true, useUnifiedTopology: true });

const TaskSchema = new mongoose.Schema({
  title: String,
  description: String
});

const Task = mongoose.model('Task', TaskSchema);

const client = redis.createClient();

app.get('/tasks', async (req, res) => {
  const key = '/tasks';
  client.get(key, async (err, reply) => {
    if (err) throw err;
    if (reply) {
      return res.send(JSON.parse(reply));
    } else {
      const tasks = await Task.find();
      client.set(key, JSON.stringify(tasks), redis.print);
      res.send(tasks);
    }
  });
});

app.post('/tasks', async (req, res) => {
  const task = new Task(req.body);
  await task.save();
  const tasks = await Task.find();
  client.set('/tasks', JSON.stringify(tasks), redis.print);
  res.send(task);
});

2. Utilisation de Redis Cluster

Utilisez Redis Cluster pour gérer un cache distribué.

const redis = require('redis');

const cluster = redis.createCluster([
  { host: '127.0.0.1', port: 6380 },
  { host: '127.0.0.1', port: 6381 },
  { host: '127.0.0.1', port: 6382 }
]);

cluster.set('key', 'value', redis.print);
cluster.get('key', (err, reply) => {
  if (err) throw err;
  console.log(reply); // Affiche : value
});

3. Utilisation de Redis avec Docker

Dockerize votre application pour faciliter le déploiement.

## Dockerfile

FROM node:14

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]
docker-compose.yml
version: '3'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
    depends_on:
      - redis

  redis:
    image: "redis:6.2"
bash
docker-compose up --build

Défi pratique : Créer un CLI tool avec caching Redis

Créez un CLI tool pour interagir avec une base de données et utiliser le caching Redis.

  1. Initialiser un projet Node.js.
  2. Installer les dépendances nécessaires (commander, redis).
  3. Créer un script CLI qui permet d'ajouter, supprimer, récupérer et mettre à jour des tâches en utilisant le caching Redis.
  4. Tester votre CLI tool.

Conclusion

Le caching avec Node.js et Redis est une technique puissante pour optimiser les performances de vos applications. En suivant ce tutoriel, vous avez appris comment mettre en place un système de caching robuste et performant pour des applications web simples à plus complexes. N'oubliez pas que le caching n'est pas une solution miracle : il est toujours important d'évaluer attentivement les besoins spécifiques de votre application avant de l'implémenter.

Besoin d'aide sur Node.js ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelle est la différence entre 'caching' et 'memoization' ?
Le caching est une technique générale pour stocker les résultats des appels aux fonctions afin de les réutiliser plus tard, tandis que la memoization est une forme spécifique de caching appliquée aux fonctions spécifiques en stockant leurs résultats en fonction de leurs arguments.
Comment installer Redis sur un système Windows ?
Pour installer Redis sur Windows, vous pouvez télécharger le package MSI à partir du site officiel de Redis. Après le téléchargement, exécutez l'installeur et suivez les instructions pour terminer l'installation.
Quelle est la bibliothèque Node.js recommandée pour interagir avec Redis ?
La bibliothèque Node.js la plus populaire pour interagir avec Redis est 'redis'. Vous pouvez l'installer via npm avec la commande 'npm install redis'. Cette bibliothèque offre une API complète et flexible pour travailler avec Redis depuis votre application Node.js.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.