Connexions Redis
Guidance côté client pour communiquer avec Redis efficacement : comment partager les connexions, comment regrouper les commandes, quelles commandes éviter en production, quand activer le cache côté client, et comment configurer les timeouts pour échouer rapidement sans casser le trafic sain.
Quand appliquer
- Créer ou examiner une configuration de client Redis (redis-py, Jedis, Lettuce, go-redis, NRedisStack).
- Effectuer beaucoup de petits appels Redis et se demander où va la latence.
- Itérer sur des espaces de clés, ensembles, hashes ou listes volumineux.
- Activer le cache côté client pour les clés chaudes.
- Ajuster les timeouts de connexion / lecture / écriture.
1. Pool ou multiplexage — jamais une connexion par requête
La plus grosse erreur dans le code client Redis est d'ouvrir une nouvelle connexion TCP pour chaque opération. Faites toujours l'un des deux :
- Pool — conservez N connexions persistantes que l'application loue par appel (redis-py
ConnectionPool, JedisJedisPooled, client go-redis). - Multiplexage — partagez une seule connexion sur toutes les requêtes (Lettuce, NRedisStack).
| Style | Utilisé par | Note |
|---|---|---|
| Pool | redis-py, Jedis, go-redis | Chaque location se bloque si le pool est épuisé ; dimensionnez le pool selon votre concurrence |
| Multiplexage | Lettuce, NRedisStack | Connexion unique ; ne peut pas porter de commandes bloquantes comme BLPOP |
# redis-py — connection pool
pool = redis.ConnectionPool(host="localhost", port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)
Voir references/pooling.md pour des exemples Python + Java + Lettuce.
2. Pipeline pour le travail en masse
Pour N commandes qui ne dépendent pas des résultats les unes des autres, envoyez-les en un seul lot avec le pipelining. Un aller-retour au lieu de N.
pipe = redis.pipeline()
for user_id in user_ids:
pipe.get(f"user:{user_id}")
results = pipe.execute()
Utilisez le pipelining non-transactionnel pour les performances, et pipeline(transaction=True) uniquement quand vous avez réellement besoin d'atomicité (voir la guidance transactions de redis-core).
Voir references/pipelining.md.
3. Éviter les commandes qui scannent tout
Tout ce qui parcourt l'espace de clés entier (ou un conteneur volumineux entier) bloque le serveur. Utilisez plutôt les variantes incrementales.
| À ne pas faire | Utilisez |
|---|---|
KEYS pattern |
Boucle SCAN cursor |
SMEMBERS large_set |
SSCAN |
HGETALL large_hash |
HSCAN |
LRANGE 0 -1 sur une liste énorme |
Paginez (LRANGE 0 100) |
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
break
Les commandes bloquantes (BLPOP, BRPOP, BLMOVE) sont différentes — elles attendent intentionnellement des données et conviennent pour les consommateurs de queue, mais toujours passer un timeout, et ne les émettre jamais sur une connexion multiplexée (Lettuce, NRedisStack).
Voir references/blocking.md.
4. Cache côté client pour les clés chaudes
Pour les données lues souvent et écrites rarement (config, feature flags, sessions à chaque requête), activez le cache côté client RESP3. Le client garde une copie locale et le serveur l'invalide sur les écritures — économisant l'aller-retour pour les lectures chaudes.
client = redis.Redis(
host="localhost",
port=6379,
protocol=3, # RESP3 est requis
cache_config=redis.CacheConfig(max_size=1000),
)
Sautez cette étape pour les workloads lourd-en-écritures ou les données qui changent constamment — le trafic d'invalidation surcharge les économies.
Voir references/client-cache.md.
5. Définir des timeouts explicites
Les défauts varient selon le client et peuvent être trop généreux. Choisissez des valeurs qui correspondent au modèle d'échec de l'application :
r = redis.Redis(
host="localhost",
socket_connect_timeout=2.0, # échouer rapidement sur les nœuds morts
socket_timeout=5.0, # ajuster au temps d'opération attendu
retry_on_timeout=True,
)
Règle d'or : timeout de connexion plus court que timeout de lecture/écriture. Timeouts serrés + retry-on-timeout pour les chemins sensibles à la latence ; timeouts plus longs pour les jobs batch.
Voir references/timeouts.md.