Quand utiliser ElastiCache Redis : accélérer les lectures RDS avec un cache distribué
Votre base RDS répond en 200-400 ms sur des requêtes identiques relancées toutes les secondes — c'est le symptôme classique d'une absence de couche cache. Ajouter ElastiCache Redis devant RDS n'est pas une optimisation cosmétique : c'est un changement architectural qui déplace la charge de lecture du moteur relationnel vers un store en mémoire conçu pour ça.
TL;DR — ElastiCache Redis face à RDS : quand et pourquoi
| Situation | Sans cache | Avec ElastiCache Redis |
|---|---|---|
| Lecture répétée du même enregistrement | Requête SQL à chaque appel | Réponse depuis la mémoire, RDS non sollicité |
| Pic de trafic soudain | Connexions RDS saturées | Cache absorbe la majorité des lectures |
| Données de session utilisateur | Stockage en base ou fichier | TTL natif, accès O(1) |
| Résultats de calculs coûteux | Recalcul à chaque requête | Résultat mis en cache jusqu'à expiration |
| Données qui changent souvent | Cache inutile ou dangereux | Invalidation explicite nécessaire |
Comment fonctionne la couche cache Redis devant RDS
Redis est un store clé-valeur en mémoire. Quand votre application lit une donnée, elle interroge Redis en premier. Si la clé existe et n'a pas expiré (cache hit), la réponse revient sans toucher RDS. Si la clé est absente ou expirée (cache miss), l'application interroge RDS, stocke le résultat dans Redis avec un TTL, puis retourne la réponse. Ce pattern s'appelle cache-aside (ou lazy loading) — c'est le plus courant sur AWS.
Pensez à Redis comme à un comptoir de restauration rapide : les plats du jour sont prêts immédiatement. Si vous commandez quelque chose hors menu, le cuisinier (RDS) le prépare, et le comptoir le garde au chaud pour la prochaine commande identique.
- Requête applicative — l'application interroge Redis avec une clé construite à partir des paramètres de la requête.
- Cache hit — Redis retourne la valeur sérialisée directement. RDS n'est pas contacté.
- Cache miss — Redis retourne nil. L'application exécute la requête SQL sur RDS.
- Mise en cache — le résultat RDS est écrit dans Redis avec un TTL défini par la logique métier.
- Invalidation — lors d'une écriture (UPDATE/DELETE), l'application supprime ou met à jour la clé Redis correspondante.
Quand ElastiCache Redis résout réellement le problème de lenteur RDS
Le cache Redis est efficace dans des conditions précises. Avant de provisionner un cluster, vérifiez que votre cas correspond à l'un de ces profils.
Données lues fréquemment, modifiées rarement
Les catalogues produits, les configurations applicatives, les données de référence (pays, devises, catégories) — ce sont les candidats idéaux. Le ratio lecture/écriture est élevé, donc le TTL peut être long sans risque de stale data significatif. Un TTL de 5 à 30 minutes est souvent raisonnable selon la tolérance métier.
Requêtes SQL coûteuses avec résultats stables
Une jointure sur 5 tables qui prend 800 ms mais retourne le même résultat pendant 10 minutes — mettez-la en cache. La clé Redis doit encoder tous les paramètres qui influencent le résultat. Si un seul paramètre change, la clé change, et vous évitez de servir un résultat incorrect.
Sessions utilisateur et tokens
Redis gère nativement l'expiration via TTL. Stocker les sessions en RDS crée une table à forte contention en écriture. Redis élimine ce problème structurellement — chaque SET avec EX est atomique et l'expiration est gérée par Redis lui-même sans job de nettoyage.
Quand le cache Redis ne résout pas le problème
Si vos lectures sont lentes parce que chaque requête porte des paramètres uniques (recherche full-text, filtres dynamiques par utilisateur), le taux de cache hit sera proche de zéro. Redis ne vous aidera pas — le problème est dans l'indexation RDS ou l'architecture de la requête. Vérifiez d'abord avec EXPLAIN ANALYZE avant de provisionner un cache.
Provisionner ElastiCache Redis sur AWS — étapes opérationnelles
Étape 1 — Créer le subnet group ElastiCache dans le même VPC que RDS
ElastiCache doit être dans le même VPC que votre application et accessible depuis les subnets privés. Le subnet group définit dans quels subnets les nœuds Redis peuvent être placés. C'est un prérequis bloquant — sans ça, la connectivité réseau ne fonctionnera pas.
aws elasticache create-cache-subnet-group \
--cache-subnet-group-name mon-redis-subnet-group \
--cache-subnet-group-description "Subnet group Redis production" \
--subnet-ids subnet-0abc123456789def0 subnet-0def987654321abc0 \
--region us-east-1
Étape 2 — Créer le security group Redis et autoriser le port 6379 depuis l'application
Le security group Redis ne doit accepter que le trafic entrant sur le port 6379 depuis le security group de vos instances applicatives. Ouvrir 0.0.0.0/0 sur un cache Redis en production est une erreur de configuration grave — Redis n'a pas d'authentification réseau par défaut sur les anciennes versions.
aws ec2 create-security-group \
--group-name redis-sg \
--description "Security group ElastiCache Redis" \
--vpc-id vpc-0123456789abcdef0 \
--region us-east-1
aws ec2 authorize-security-group-ingress \
--group-id sg-0redis1234567890a \
--protocol tcp \
--port 6379 \
--source-group sg-0app1234567890b \
--region us-east-1
Étape 3 — Créer le cluster Redis (mode Serverless ou cluster classique)
AWS propose deux modes : ElastiCache Serverless (capacité gérée automatiquement) et les clusters avec nœuds explicites. Pour un premier déploiement avec charge prévisible, un cluster avec un nœud primary et un replica en mode non-cluster est plus simple à opérer et à monitorer. Activez le chiffrement en transit (--transit-encryption-enabled) et l'authentification par token (--auth-token) en production.
🔽 Cliquer pour voir la commande de création du cluster Redis
aws elasticache create-replication-group \
--replication-group-id mon-redis-prod \
--replication-group-description "Cache Redis production" \
--cache-node-type cache.t4g.medium \
--engine redis \
--engine-version 7.0 \
--num-cache-clusters 2 \
--cache-subnet-group-name mon-redis-subnet-group \
--security-group-ids sg-0redis1234567890a \
--transit-encryption-enabled \
--auth-token "VotreTokenSecretMinimum16Chars" \
--at-rest-encryption-enabled \
--automatic-failover-enabled \
--region us-east-1
Étape 4 — Récupérer l'endpoint primaire pour la configuration applicative
Une fois le cluster en état available, récupérez l'endpoint. En mode non-cluster, utilisez l'endpoint du replication group (primary endpoint) pour les écritures et le reader endpoint pour les lectures — cela distribue la charge de lecture sur les replicas.
aws elasticache describe-replication-groups \
--replication-group-id mon-redis-prod \
--query 'ReplicationGroups[0].NodeGroups[0].PrimaryEndpoint' \
--region us-east-1
Étape 5 — Implémenter le pattern cache-aside dans l'application
Le SDK AWS ne gère pas la logique cache-aside — c'est votre code applicatif qui l'implémente. Voici le pattern en Python avec redis-py. La clé doit être déterministe et unique par combinaison de paramètres. Le TTL est en secondes.
🔽 Cliquer pour voir l'implémentation cache-aside Python
import redis
import json
import hashlib
r = redis.Redis(
host='mon-redis-prod.xxxxx.ng.0001.use1.cache.amazonaws.com',
port=6379,
ssl=True,
password='VotreTokenSecretMinimum16Chars',
decode_responses=True
)
def get_produit(produit_id: int, db_conn):
cache_key = f"produit:{produit_id}"
# Tentative cache hit
cached = r.get(cache_key)
if cached is not None:
return json.loads(cached)
# Cache miss — interroger RDS
cursor = db_conn.cursor()
cursor.execute("SELECT * FROM produits WHERE id = %s", (produit_id,))
row = cursor.fetchone()
if row is None:
return None
# Mettre en cache avec TTL de 10 minutes
r.set(cache_key, json.dumps(row), ex=600)
return row
def update_produit(produit_id: int, data: dict, db_conn):
cursor = db_conn.cursor()
cursor.execute(
"UPDATE produits SET nom = %s, prix = %s WHERE id = %s",
(data['nom'], data['prix'], produit_id)
)
db_conn.commit()
# Invalider le cache après écriture
r.delete(f"produit:{produit_id}")
Diagnostiquer l'efficacité du cache — métriques CloudWatch à surveiller
Provisionner Redis sans monitorer le taux de hit, c'est conduire sans tableau de bord. Ces métriques CloudWatch sont disponibles nativement pour ElastiCache.
- CacheHits / CacheMisses — ratio fondamental. Un taux de hit inférieur à 80% sur des données supposément stables indique un problème de stratégie de clés ou de TTL trop court.
- CurrConnections — nombre de connexions actives. Un pic soudain peut indiquer que l'application ne réutilise pas les connexions (absence de connection pooling).
- Evictions — nombre d'entrées expulsées avant expiration du TTL parce que la mémoire est pleine. Des évictions fréquentes signifient que le nœud est sous-dimensionné ou que la politique d'éviction (
maxmemory-policy) n'est pas adaptée. - ReplicationLag — délai entre le nœud primaire et les replicas. Un lag élevé peut entraîner des lectures stale depuis les replicas.
aws cloudwatch get-metric-statistics \
--namespace AWS/ElastiCache \
--metric-name CacheHits \
--dimensions Name=CacheClusterId,Value=mon-redis-prod-0001-001 \
--start-time 2024-01-15T00:00:00Z \
--end-time 2024-01-15T01:00:00Z \
--period 300 \
--statistics Sum \
--region us-east-1
Le piège classique : stale data et invalidation incohérente
Voici le scénario qu'on voit régulièrement en production : l'équipe active le cache, les temps de réponse s'améliorent, et deux semaines plus tard un bug remonte — des utilisateurs voient des prix incorrects. L'investigation montre que le code d'invalidation du cache n'est appelé que depuis un seul service, mais qu'un second service met aussi à jour la table produits directement en base sans passer par la couche d'invalidation.
Le symptôme : CloudWatch montre un taux de hit de 95%, RDS est soulagé, tout semble parfait. Mais les données servies sont fausses pour les enregistrements modifiés par le second service.
La cause réelle : l'invalidation de cache n'est pas colocalisée avec la logique d'écriture — elle est dans la couche service, pas dans la couche repository. Quand un second chemin d'écriture bypasse la couche service, le cache n'est jamais invalidé.
Le correctif : centraliser toute écriture sur une entité dans une seule couche repository qui garantit l'invalidation. Alternativement, utiliser un TTL court (30-60 secondes) pour les données à cohérence critique, en acceptant une fenêtre de stale data bornée plutôt qu'une incohérence indéterminée.
IAM et sécurité — accès applicatif à ElastiCache
ElastiCache Redis ne s'intègre pas directement avec IAM pour l'authentification des connexions Redis. L'accès réseau est contrôlé par les security groups (VPC). Pour l'authentification au niveau Redis, utilisez les mécanismes suivants selon la version :
- Redis AUTH (toutes versions) — token partagé configuré via
--auth-tokenà la création. - RBAC avec Redis 6+ — ElastiCache supporte les utilisateurs et groupes d'utilisateurs Redis pour un contrôle d'accès plus granulaire via
aws elasticache create-user.
Pour les permissions IAM sur les opérations de gestion ElastiCache (création, modification, suppression de clusters), voici une politique minimale pour un rôle applicatif qui n'a besoin que de décrire les endpoints :
🔽 Cliquer pour voir la politique IAM minimale
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DescribeElastiCacheEndpoints",
"Effect": "Allow",
"Action": [
"elasticache:DescribeReplicationGroups",
"elasticache:DescribeCacheClusters"
],
"Resource": "*"
}
]
}
Conclusion — ElastiCache Redis et RDS : une architecture complémentaire
ElastiCache Redis ne remplace pas RDS — il absorbe les lectures répétitives pour que RDS puisse se concentrer sur ce qu'il fait bien : les transactions, les jointures complexes, et la cohérence des données. La décision d'ajouter un cache doit partir d'une mesure réelle du taux de répétition des requêtes, pas d'une intuition sur la lenteur.
Avant de provisionner, répondez à ces trois questions : quel est mon ratio lecture/écriture sur les tables concernées ? Quelle tolérance métier ai-je pour des données légèrement stale ? Est-ce que toutes mes écritures passent par un chemin centralisé qui peut invalider le cache ? Si vous ne pouvez pas répondre à la troisième, résolvez ça d'abord.
Pour aller plus loin, consultez la documentation officielle ElastiCache Redis et le guide Best Practices ElastiCache.
Glossaire
| Terme | Définition |
|---|---|
| Cache-aside (Lazy Loading) | Pattern où l'application gère elle-même la lecture depuis le cache et le fallback vers la base de données. Le cache n'est peuplé qu'à la demande. |
| TTL (Time To Live) | Durée en secondes après laquelle une clé Redis expire automatiquement. Contrôle la fraîcheur des données cachées. |
| Cache hit / Cache miss | Hit : la clé demandée existe dans Redis. Miss : la clé est absente ou expirée, nécessitant un accès à RDS. |
| Eviction | Suppression forcée d'entrées Redis avant expiration du TTL quand la mémoire allouée est saturée. Contrôlé par la politique maxmemory-policy. |
| Replication Group | Unité logique ElastiCache regroupant un nœud primaire et ses replicas. Fournit la haute disponibilité et le basculement automatique. |
Commentaires
Enregistrer un commentaire