Cas d'utilisation de Redis : Cache, Files d'attente et Limitation de débit

Backend2026-10-06TryQuickToolBox

Vous avez construit une application web qui fonctionne bien avec quelques utilisateurs, mais à mesure que le trafic augmente, vous remarquez des chargements de page lents, des tâches en arrière-plan dupliquées et des API bombardées par des clients abusifs. Ce sont des problèmes de mise à l'échelle classiques que Redis peut résoudre élégamment. Redis est un magasin de données en mémoire qui excelle dans trois tâches principales : le cache, les files d'attente et la limitation de débit. Dans cet article, nous explorerons chaque cas d'utilisation avec des exemples pratiques et des bonnes pratiques.

Pourquoi Redis pour ces cas d'utilisation ?

Redis stocke les données en mémoire, ce qui le rend incroyablement rapide—souvent avec des temps de réponse inférieurs à la milliseconde. Il prend en charge des structures de données riches comme les chaînes, les listes, les ensembles, les ensembles triés et les hachages, qui correspondent naturellement au cache, aux files d'attente et à la limitation de débit. Il offre également des opérations atomiques, pub/sub et des options de persistance, ce qui en fait un outil polyvalent pour les développeurs backend.

1. Cache avec Redis

Le cache est le cas d'utilisation le plus courant de Redis. En stockant les données fréquemment consultées dans Redis, vous réduisez la charge de la base de données et accélérez les réponses.

Comment fonctionne le cache

Lorsqu'une requête arrive, vérifiez si les données existent dans Redis. Si oui (succès du cache), retournez-les directement. Sinon (échec du cache), récupérez-les depuis la base de données, stockez-les dans Redis avec un temps d'expiration, et retournez-les. Ce modèle est appelé cache-aside.

// Exemple Node.js utilisant ioredis
const Redis = require('ioredis');
const redis = new Redis();

async function getUser(userId) {
  const cacheKey = `user:${userId}`;
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached);

  const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
  await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600); // TTL d'une heure
  return user;
}

Bonnes pratiques pour le cache

Stratégies d'invalidation du cache

L'invalidation est difficile. Les stratégies courantes incluent :

2. Files d'attente avec Redis

Les files d'attente découplent les tâches chronophages du cycle requête-réponse. Par exemple, l'envoi d'e-mails, le traitement d'images ou la génération de rapports peuvent être effectués de manière asynchrone.

Implémentation d'une file d'attente simple

Les listes Redis sont parfaites pour les files d'attente. Utilisez LPUSH pour ajouter des tâches à gauche et BRPOP pour bloquer et retirer de la droite (FIFO).

// Producteur : ajouter une tâche
await redis.lpush('email_queue', JSON.stringify({ to: 'user@example.com', subject: 'Welcome' }));

// Consommateur : traiter la tâche (dans un worker)
while (true) {
  const job = await redis.brpop('email_queue', 0); // 0 = bloquer indéfiniment
  const { to, subject } = JSON.parse(job[1]);
  await sendEmail(to, subject);
}

Files d'attente fiables avec BRPOPLPUSH

Pour éviter de perdre des tâches si un worker plante, utilisez BRPOPLPUSH pour déplacer atomiquement la tâche vers une liste de traitement. Après un traitement réussi, retirez-la de la liste de traitement. Si le worker meurt, un autre worker peut récupérer les tâches de la liste de traitement.

const job = await redis.brpoplpush('email_queue', 'processing_queue', 0);
try {
  // traiter la tâche
  await redis.lrem('processing_queue', 1, job);
} catch (err) {
  // gérer l'erreur, peut-être remettre en file d'attente
}

Bibliothèques de files d'attente dédiées

Pour la production, envisagez des bibliothèques comme Bull (Node.js), RQ (Python) ou Sidekiq (Ruby). Elles fournissent des tentatives, une planification et une surveillance prêtes à l'emploi.

3. Limitation de débit avec Redis

La limitation de débit protège votre API contre les abus et assure une utilisation équitable. Les opérations atomiques de Redis le rendent idéal pour compter les requêtes.

Limitation de débit à fenêtre fixe

Incrémentez un compteur pour chaque utilisateur par fenêtre de temps. Si le compteur dépasse la limite, rejetez la requête.

async function isAllowed(userId, limit = 100, windowSec = 60) {
  const key = `rate:${userId}:${Math.floor(Date.now() / 1000 / windowSec)}`;
  const count = await redis.incr(key);
  if (count === 1) await redis.expire(key, windowSec);
  return count