Cas d'usage Redis : cache, files d'attente et rate limiting
Vous avez développé une application web qui fonctionne, mais à mesure que le trafic augmente, vous constatez des temps de chargement lents, des goulots d'étranglement au niveau de la base de données et quelques interruptions de service. Ce sont des problèmes de scalabilité courants. Redis, un magasin de données en mémoire, peut résoudre bon nombre de ces problèmes avec élégance. Dans cet article, nous allons explorer trois cas d'usage pratiques de Redis : le cache, les files d'attente et le rate limiting. Vous apprendrez à implémenter chacun d'eux avec des exemples de code et des bonnes pratiques.
Pourquoi Redis ?
Redis est un magasin clé-valeur open-source en mémoire, connu pour sa rapidité et sa polyvalence. Il prend en charge des structures de données telles que les chaînes, les listes, les ensembles, les hachages et les ensembles triés, ce qui le rend adapté à un large éventail de tâches. Comme il conserve les données en mémoire, les lectures et écritures sont extrêmement rapides — souvent en dessous de la milliseconde. Bien qu'il ne remplace pas une base de données principale, il excelle comme outil complémentaire pour la performance et la coordination.
1. Le cache avec Redis
La mise en cache est le cas d'usage le plus courant de Redis. En stockant les données fréquemment consultées dans Redis, vous réduisez la charge sur votre base de données principale et accélérez les réponses.
Comment implémenter le cache
- Vérifiez d'abord Redis : lorsqu'une requête arrive, recherchez les données dans Redis à l'aide d'une clé unique.
- En cas d'échec du cache : si les données ne sont pas dans Redis, récupérez-les depuis votre base de données.
- Stockez dans Redis : enregistrez le résultat dans Redis avec une durée d'expiration (TTL) pour éviter les données obsolètes.
- Retournez les données : envoyez les données au client.
Voici un exemple simple en Python utilisant redis-py :
import redis
import json
r = redis.Redis(host='localhost', port=6379, db=0)
def get_user(user_id):
cache_key = f"user:{user_id}"
cached = r.get(cache_key)
if cached:
return json.loads(cached)
# Simulate DB fetch
user = fetch_user_from_db(user_id)
r.setex(cache_key, 3600, json.dumps(user)) # cache for 1 hour
return user
Bonnes pratiques :
- Utilisez des noms de clés explicites avec des deux-points, par exemple
user:123. - Définissez un TTL pour éviter les données obsolètes et la surcharge mémoire.
- Envisagez des stratégies d'invalidation du cache : write-through, write-behind ou expiration basée sur le temps.
- Pour les objets complexes, sérialisez avec JSON ou MessagePack.
2. Les files d'attente avec Redis
Les listes et les streams Redis sont parfaits pour construire des files d'attente de messages simples. Ils vous permettent de découpler les tâches chronophages (comme l'envoi d'e-mails ou le traitement d'images) du flux de requêtes principal, améliorant ainsi la réactivité.
Utiliser les listes comme files d'attente
Les listes Redis prennent en charge des opérations atomiques de push et pop. Utilisez LPUSH pour ajouter des tâches à gauche et BRPOP pour bloquer et dépiler à droite, créant ainsi une file d'attente FIFO.
# Producer: add a job
r.lpush('job_queue', json.dumps({'task': 'send_email', 'to': 'user@example.com'}))
# Consumer: process jobs
while True:
_, job_data = r.brpop('job_queue', timeout=30)
job = json.loads(job_data)
process_job(job)
Considérations :
- Fiabilité : les listes ne sont pas persistantes par défaut ; activez la persistance AOF ou RDB si nécessaire.
- Livraison au moins une fois : utilisez
BRPOPLPUSHpour déplacer les tâches vers une liste de traitement, puis supprimez-les une fois terminées. - Streams : pour des cas d'usage plus avancés (groupes de consommateurs, accusés de réception), envisagez les Redis Streams.
3. Le rate limiting avec Redis
Le rate limiting protège votre API contre les abus et garantit une utilisation équitable. Les opérations atomiques et l'expiration de Redis en font un choix idéal pour implémenter des limiteurs de débit.
Rate limiting à fenêtre fixe
Dans une fenêtre fixe, vous autorisez N requêtes par fenêtre temporelle (par exemple, 100 requêtes par heure). Utilisez INCR et EXPIRE pour suivre les compteurs.
def is_rate_limited(user_id, limit=100, window=3600):
key = f"rate:{user_id}"
current = r.incr(key)
if current == 1:
r.expire(key, window)
return current > limit
La fenêtre glissante avec des ensembles triés offre une limitation plus fluide. Stockez les horodatages des requêtes dans un ensemble trié et supprimez les anciennes entrées.
def is_rate_limited_sliding(user_id, limit=100, window=3600):
key = f"rate:{user_id}"
now = time.time()
pipeline = r.pipeline()
pipeline.zremrangebyscore(key, 0, now - window)
pipeline.zadd(key, {now: now})
pipeline.zcard(key)
pipeline.expire(key, window)
_, _, count, _ = pipeline.execute()
return count > limit
Bonnes pratiques :
- Utilisez une clé unique par utilisateur ou par IP.
- Combinez avec un middleware pour une intégration propre.
- Envisagez d'utiliser des modules Redis comme
redis-cellpour des algorithmes avancés.
Comparaison des cas d'usage
| Cas d'usage | Structure de données Redis | Avantage principal |
|---|---|---|
| Cache | String, Hash | Réduire la charge de la base de données, lectures plus rapides |
| Files d'attente | List, Stream | Découpler les tâches, améliorer la réactivité |
| Rate Limiting | String, Sorted Set | Protéger les API, garantir une utilisation équitable |
FAQ
Redis est-il persistant ?
Redis offre une persistance via des snapshots RDB et des journaux AOF, mais c'est avant tout un magasin en mémoire. Pour les données critiques, prévoyez toujours une sauvegarde ou utilisez une base de données principale.
Puis-je utiliser Redis pour le stockage de sessions ?
Oui, Redis est couramment utilisé pour le stockage de sessions en raison de sa rapidité et de son expiration automatique. Il vous permet de partager les sessions entre plusieurs serveurs.
Que se passe-t-il si Redis tombe en panne ?
Si Redis est indisponible, votre application doit basculer gracieusement vers la base de données ou renvoyer les données mises en cache depuis un cache local. Implémentez des disjoncteurs pour éviter les défaillances en cascade.
Prêt à optimiser votre application web ? Commencez par intégrer Redis pour le cache, les files d'attente ou le rate limiting. Pour des tâches rapides comme le formatage JSON ou l'analyse de logs, découvrez notre JSON Formatter et notre Nginx Log Analyzer.