Introduction aux Systèmes NoSQL et Redis
Les bases de données NoSQL, en particulier les magasins de clé-valeur, ont gagné en popularité pour leur capacité à gérer des volumes massifs de données et des débits élevés. Parmi elles, Redis se distingue comme un choix privilégié pour la mise en cache, les bases de données et les courtiers de messages.
Capacités Principales de Redis
- Types de Données Variés : Prend en charge les chaînes, hachages, listes, ensembles, ensembles triés, bitmaps et hyperloglogs.
- Persistance des Données : Offre des mécanismes RDB (snapshot) et AOF (journal d'opérations) pour sauvegarder les données sur disque.
- Stratégies de Gestion Mémoire : Diverses politiques d'éviction pour optimiser l'utilisation de la RAM.
- Transactions Atomiques : Supporte des opérations groupées avec des garanties transactionnelles légères.
- Messagerie Avancée : Fonctionnalités de publication/abonnement pour les architectures de microservices.
- Haute Disponibilité : Architectures maître-réplique et Sentinel pour la tolérance aux pannes.
- Distribution Horizontale : Support natif pour le clustering distribué.
Comparaison des Solutions de Cache en Entreprise
Historiquement, plusieurs solutions de cache ont été utilisées en entreprise :
Memcached
- Avantages : Excellentes performances en lecture/écriture pour des données simples, architecture multi-cœurs/multi-threads.
- Inconvénients : Aucune persistance, la gestion du cluster est côté client, moins de types de données.
Redis
- Avantages : Performances élevées, nombreux types de données, persistance, haute disponibilité, clustering distribué, architecture single-thread très efficace.
- Inconvénients : Historiquement, les performances multi-threads pures étaient légèrement inférieures à Memcached pour certaines charges de travail, bien que cela ait évolué avec les versions récentes.
Redis est souvent préféré pour les applications nécessitant une plus grande flexibilité des données et des garanties de persistance, comme dans les plateformes de commerce électronique, les réseaux sociaux et les jeux en ligne.
Installation et Configuration Basique de Redis
Redis est développé en langage C, ce qui lui confère une vitesse et une efficacité remarquables. Son architecture mono-thread simplifie la gestion de la concurrence.
Processus d'Installation
Pour installer Redis, il est généralement recommandé de le compiler à partir des sources pour une performance optimale. Les étapes sont les suivantes :
# Télécharger l'archive depuis le site officiel
wget http://download.redis.io/releases/redis-7.0.5.tar.gz
# Extraire l'archive
tar xzf redis-7.0.5.tar.gz
mv redis-7.0.5 redis
# Installer les dépendances (GCC, make, etc.)
yum install -y gcc make automake autoconf libtool # Pour systèmes basés sur RPM
# ou apt install -y gcc make automake autoconf libtool # Pour systèmes basés sur Debian
# Compiler Redis
cd redis
make
# Installer les binaires dans un emplacement standard (optionnel, mais recommandé)
make install
# Ajouter les binaires au PATH (si non installés via make install)
echo 'export PATH=/path/to/redis/src:$PATH' >> ~/.bashrc
source ~/.bashrc
Configuraton d'une Instance Redis
Une configuration de base pour un service Redis autonome peut être créée comme suit :
mkdir -p /opt/redis_data/6379
cat > /opt/redis_data/6379/redis.conf <<EOF
daemonize yes
bind 127.0.0.1
port 6379
logfile /opt/redis_data/6379/redis_6379.log
dir /opt/redis_data/6379
dbfilename dump_6379.rdb
protected-mode yes
EOF
# Démarrer le serveur Redis avec la configuration
redis-server /opt/redis_data/6379/redis.conf
daemonize yes: Exécute Redis en arrière-plan.bind 127.0.0.1: N'écoute que sur l'interface locale par défaut. Pour un accès externe, spécifiez l'IP du serveur ou0.0.0.0(attention à la sécurité).port 6379: Le port d'écoute.logfile: Chemin du fichier journal.dir: Répertoire de travail pour les fichiers de persistance.dbfilename: Nom du fichier RDB pour la persistance.protected-mode yes: Active le mode protégé, limitant l'accès aux clients locaux sans configuration explicite debindourequirepass. Il est fortement recommandé de le laisser activé ou de configurer un mot de passe.
Sécurisation de l'Accès
Pour sécuriser votre instance Redis, vous pouvez définir un mot de passe et lier le serveur à une adresse IP spécifique :
echo "bind 10.0.0.10 127.0.0.1" >> /opt/redis_data/6379/redis.conf
echo "requirepass votre_mot_de_passe_secret" >> /opt/redis_data/6379/redis.conf
# Redémarrer Redis pour appliquer les changements
redis-cli -p 6379 shutdown
redis-server /opt/redis_data/6379/redis.conf
Pour se connecter avec authentification :
redis-cli -p 6379 -a votre_mot_de_passe_secret
# Ou après la connexion
redis-cli -p 6379
AUTH votre_mot_de_passe_secret
Persistance des Données Redis
Redis propose deux principaux mécanismes pour sauvegarder les données en mémoire sur disque : RDB et AOF.
RDB (Redis Database Backup)
Le mode RDB crée des instantanés (snapshots) de l'ensemble du jeu de données à des intervalles spécifiés. C'est un format binaire compact.
- Avantages :
- Très rapide pour la restauration et les sauvegardes.
- Compact et efficace pour la réplication maître-réplique.
- Inconvénients :
- Risque de perte de données entre deux instantanés en cas de crash.
Configuration exemple dans redis.conf :
save 900 1 # Sauvegarde si 1 changement en 15 minutes
save 300 10 # Sauvegarde si 10 changements en 5 minutes
save 60 10000 # Sauvegarde si 10000 changements en 60 secondes
dbfilename mydump.rdb
dir /opt/redis_data/6379
AOF (Append-Only File)
Le mode AOF enregistre chaque commande d'écriture reçue par le serveur sous forme de journal. Au redémarrage, Redis rejoue ces commandes pour reconstruire l'état des données.
- Avantages :
- Minimise la perte de données (peut être configuré pour chaque écriture).
- Le fichier AOF est lisible par l'homme.
- Inconvénients :
- Le fichier AOF est généralement plus grand que le RDB.
- La restauration peut être plus lente que RDB.
Configuration exemple dans redis.conf :
appendonly yes
appendfsync everysec # Synchronise le fichier AOF toutes les secondes (bon compromis performance/sécurité)
# appendfsync always # Synchronise à chaque écriture (très sûr, mais lent)
# appendfsync no # Laisse l'OS gérer la synchronisation (rapide, moins sûr)
Combinaison des Deux
Depuis Redis 4.0, il est possible de combiner RDB et AOF (mode hybride) pour tirer parti des avantages de chacun : le fichier AOF contient un snapshot RDB au démarrage, suivi des commandes AOF incrémentales, ce qui accélère le redémarrage tout en assurant une meilleure résilience. Pour l'activer, il suffit d'avoir appendonly yes et aof-use-rdb-preamble yes (par défaut depuis Redis 5).
Types de Données Fondamentaux de Redis
Redis prend en charge un large éventail de types de données, chacun optimisé pour des cas d'utilisation spécifiques.
Opérations Génériques sur les Clés
Avant de plonger dans les types spécifiques, voici quelques commandes universelles pour la gestion des clés :
# Lister les clés (utiliser avec prudence en production sur de grands datasets)
KEYS user:*
TYPE maClef # Retourne le type de valeur stockée
EXPIRE maClef 30 # Définit une expiration de 30 secondes
TTL maClef # Retourne le temps de vie restant en secondes
PERSIST maClef # Supprime l'expiration
DEL maClef # Supprime une clé
EXISTS maClef # Vérifie l'existence d'une clé
RENAME ancienneClef nouvelleClef # Renomme une clé
Chaînes (Strings)
Le type le plus simple, stockant une séquence d'octets. Idéal pour les sessions, les compteurs ou les données binaires.
Exemples d'Opérations
SET utilisateur:123 "Alice" # Définit une valeur
GET utilisateur:123 # Récupère la valeur
MSET user:1 "Bob" user:2 "Charlie" # Définit plusieurs clés en une fois
INCR visites:page_accueil # Incrémente un compteur
DECR solde:compte:456 # Décrémente un compteur
APPEND message " World" # Ajoute à une chaîne existante
Hachages (Hashes)
Permettent de stocker des paires champ-valeur au sein d'une seule clé. Similaire aux objets JSON ou aux enregistrements de base de données.
Exemples d'Opérations
HSET produit:789 nom "Ordinateur Portable" prix 1200 stock 50
HGET produit:789 nom # Récupère un champ spécifique
HMGET produit:789 nom prix # Récupère plusieurs champs
HGETALL produit:789 # Récupère tous les champs et leurs valeurs
HINCRBY produit:789 stock -5 # Décrémente le stock de 5
HDEL produit:789 prix # Supprime un champ
Listes (Lists)
Des collections ordonnées de chaînes. Utiles pour les files d'attente, les historiques ou les flux d'actualités.
Exemples d'Opérations
LPUSH historique:user:101 "Page A" "Page B" "Page C" # Ajoute des éléments à gauche (tête)
RPUSH file:taches "Tache 1" "Tache 2" # Ajoute des éléments à droite (queue)
LPOP historique:user:101 # Retire et retourne l'élément le plus à gauche
RPOP file:taches # Retire et retourne l'élément le plus à droite
LRANGE historique:user:101 0 2 # Récupère les 3 premiers éléments (index 0 à 2)
Ensembles (Sets)
Collections non ordonnées de chaînes uniques. Idéales pour les tags, les amis ou les éléments uniques.
Exemples d'Opérations
SADD utilisateurs:premium "user:1" "user:5" "user:10"
SADD utilisateurs:actifs "user:5" "user:15" "user:20"
SMEMBERS utilisateurs:premium # Liste tous les membres
SISMEMBER utilisateurs:premium "user:1" # Vérifie si un membre existe
SINTER utilisateurs:premium utilisateurs:actifs # Intersection (utilisateurs à la fois premium et actifs)
SUNION utilisateurs:premium utilisateurs:actifs # Union (tous les utilisateurs premium ou actifs)
SDIFF utilisateurs:premium utilisateurs:actifs # Différence (utilisateurs premium mais pas actifs)
SREM utilisateurs:premium "user:1" # Retire un membre
Ensembles Triés (Sorted Sets)
Similaires aux ensembles, mais chaque membre est associé à un score flottant, permettant de les ordonner. Parfaits pour les classements (leaderboards) ou les éléments prioritaires.
Exemples d'Opérations
ZADD classement:jeu 100 "JoueurA" 250 "JoueurB" 180 "JoueurC"
ZINCRBY classement:jeu 50 "JoueurA" # Augmente le score de JoueurA de 50
ZRANGE classement:jeu 0 -1 WITHSCORES # Affiche le classement du plus petit au plus grand score
ZREVRANGE classement:jeu 0 2 WITHSCORES # Affiche le top 3 (scores les plus élevés)
ZSCORE classement:jeu "JoueurB" # Récupère le score d'un joueur
Publication/Abonnement (Pub/Sub)
Redis peut fonctionner comme un système de messagerie, où les clients s'abonnent à des canaux et reçoivent les messages publiés sur ces canaux.
Exemple d'Utilisation
# Fenêtre 1 (Abonné)
SUBSCRIBE alertes_systeme
# Fenêtre 2 (Éditeur)
PUBLISH alertes_systeme "Serveur web en surcharge!"
Les abonnés ne reçoivent que les messages publiés après leur abonnement. Il n'y a pas de persistance des messages pour les abonnés déconnectés.
Transactions Redis (Optimistic Locking)
Les transactions Redis permettent d'exécuter un groupe de commandes de manière atomique. Elles sont basées sur une file d'attente et un mécanisme de verrouillage optimiste.
Processus Transactionnel
WATCH mon_compteur # Surveille 'mon_compteur' pour les modifications concurrentes
MULTI # Démarre la transaction (les commandes sont mises en file d'attente)
INCR mon_compteur
SET message "Transaction executée"
EXEC # Exécute toutes les commandes en file d'attente.
# Si 'mon_compteur' a été modifié par un autre client depuis WATCH,
# la transaction échoue.
Si la commande DISCARD est exécutée avant EXEC, toutes les commandes en file d'attente sont abandonnées. Les transactions Redis garantissant que toutes les commandes d'une transaction sont exécutées séquentielement et atomiquement, ou aucune ne l'est, à moins qu'une commande en file d'attente ne soit syntaxiquement incorrecte.
Réplication Maître-Réplique (Master-Replica)
La réplication permet d'avoir des copies des données Redis, améliorant la lecture des performances et offrant une base pour la haute disponibilité.
Principe de Fonctionnement
- Une réplique se connecte au maître et envoie une commande
PSYNC(synchronisation partielle) ouSYNC(synchronisation complète). - Le maître génère un snapshot RDB de son jeu de données et l'envoie à la réplique.
- Pendant que le RDB est transféré, le maître met en tampon toutes les commandes d'écriture reçues.
- La réplique charge le snapshot RDB.
- Le maître envoie les commandes mises en tampon à la réplique, qui les exécute.
- Une fois synchronisée, la réplique reçoit en continu toutes les nouvelles commandes d'écriture du maître.
Configuration d'un Cluster Maître-Réplique
Nous allons configurer trois instances : 6380 (maître), 6381 et 6382 (répliques).
Fichiers de Configuration
# Configuration du maître (6380)
cat > /opt/redis_data/6380/redis.conf <<EOF
port 6380
daemonize yes
pidfile /opt/redis_data/6380/redis_6380.pid
logfile "/opt/redis_data/6380/redis_6380.log"
dbfilename dump_6380.rdb
dir /opt/redis_data/6380
requirepass mysecurepass
masterauth mysecurepass
EOF
# Configuration de la première réplique (6381)
cat > /opt/redis_data/6381/redis.conf <<EOF
port 6381
daemonize yes
pidfile /opt/redis_data/6381/redis_6381.pid
logfile "/opt/redis_data/6381/redis_6381.log"
dbfilename dump_6381.rdb
dir /opt/redis_data/6381
requirepass mysecurepass
masterauth mysecurepass
EOF
# Configuration de la seconde réplique (6382)
cat > /opt/redis_data/6382/redis.conf <<EOF
port 6382
daemonize yes
pidfile /opt/redis_data/6382/redis_6382.pid
logfile "/opt/redis_data/6382/redis_6382.log"
dbfilename dump_6382.rdb
dir /opt/redis_data/6382
requirepass mysecurepass
masterauth mysecurepass
EOF
Démarrage et Connexion
redis-server /opt/redis_data/6380/redis.conf
redis-server /opt/redis_data/6381/redis.conf
redis-server /opt/redis_data/6382/redis.conf
# Configurer 6381 et 6382 comme répliques de 6380
redis-cli -p 6381 -a mysecurepass SLAVEOF 127.0.0.1 6380
redis-cli -p 6382 -a mysecurepass SLAVEOF 127.0.0.1 6380
Vérification de l'État
redis-cli -p 6380 -a mysecurepass INFO replication
redis-cli -p 6381 -a mysecurepass INFO replication
Pour désactiver la réplication sur une réplique :
redis-cli -p 6382 -a mysecurepass SLAVEOF NO ONE
Redis Sentinel pour la Haute Disponibilité
Redis Sentinel est un système de surveillance qui assure la haute disponibilité en détectant les pannes du maître et en promouvant automatiquement une réplique au rang de nouveau maître.
Fonctionnalités de Sentinel
- Surveillance : Vérifie constamment que les instances Redis (maître et répliques) fonctionnent correctement.
- Notification : Peut alerter les administrateurs en cas de problème.
- Basculement Automatique (Failover) : Déclenche la promotion d'une réplique en maître lorsqu'un maître est jugé défaillant.
- Reconfiguration : Met à jour la configuration des répliques pour qu'elles suivent le nouveau maître.
Déploiement de Redis Sentinel
Un quorum de Sentinels est recommandé pour éviter les faux positifs. Ici, nous configurons un seul Sentinel pour l'exemple.
Configuration de Sentinel
mkdir -p /opt/redis_sentinel/26380
cat > /opt/redis_sentinel/26380/sentinel.conf <<EOF
port 26380
dir "/opt/redis_sentinel/26380"
# Surveille un maître nommé 'monmaitre' à 127.0.0.1:6380, avec un quorum de 1
sentinel monitor monmaitre 127.0.0.1 6380 1
# Temps en ms après lequel un maître est considéré comme hors ligne si non-répondant
sentinel down-after-milliseconds monmaitre 5000
# Mot de passe pour l'authentification au maître
sentinel auth-pass monmaitre mysecurepass
EOF
Démarrage de Sentinel
redis-sentinel /opt/redis_sentinel/26380/sentinel.conf &> /tmp/sentinel.log &
Test de Basculement
Pour tester, arrêtez l'instance Redis maître (6380) :
redis-cli -p 6380 -a mysecurepass shutdown
Observez les logs de Sentinel et vérifiez l'état de réplication des autres instances : une réplique (par exemple 6381) devrait être promue maître.
redis-cli -p 6381 -a mysecurepass INFO replication
Une fois l'ancien maître (6380) redémarré, il devrait automatiquement devenir une réplique du nouveau maître.
redis-server /opt/redis_data/6380/redis.conf
Redis Cluster
Redis Cluster permet de distribuer automatiquement les données sur plusieurs nœuds Redis, offrant une scalabilité horizontale et une haute disponibilité sans Sentinel externe.
Principes de Communication et Distribution des Données
- Protocole Gossip : Les nœuds du cluster communiquent entre eux via le protocole Gossip (messages PING, PONG, MEET, FAIL) pour découvrir d'autres nœuds, vérifier leur état de santé et échanger des métadonnées du cluster. Le port de communication du cluster est le port de base + 10000 (ex: 7000 devient 17000).
- Slots de Hachage : Le cluster utilise 16384 "slots de hachage". Chaque clé est mappée à l'un de ces slots en utilisant un algorithme
CRC16(clé) % 16384. - Distribution des Slots : Ces 16384 slots sont distribués entre les nœuds maîtres du cluster. Chaque maître est responsable d'une plage de slots.
- Redirection Client : Si un client tente d'accéder à une clé dont le slot est géré par un autre nœud, le nœud actuel répondra avec une redirection
MOVED, indiquant au client le nœud correct.
Haute Disponibilité du Cluster
Chaque maître dans un cluster Redis peut avoir une ou plusieurs répliques. En cas de défaillance d'un maître, une de ses répliques est automatiquement promue pour prendre sa place. Le cluster continue de fonctionner tant qu'une majorité de maîtres (et leurs répliques) sont disponibles.
Déploiement d'un Cluster Redis
Un cluster Redis minimal fonctionnel nécessite au moins trois nœuds maîtres, chacun avec au moins une réplique. Nous allons configurer 6 instances Redis pour former 3 maîtres et 3 répliques.
Pré-requis : Ruby et le gem redis
L'outil de gestion de cluster redis-trib.rb (utilisé ici pour la compatibilité avec l'exemple original, mais redis-cli --cluster est préféré pour Redis 5+) nécessite Ruby et le gem redis.
yum install -y ruby rubygems
gem install redis -v 3.3.3 # Ou une version compatible avec votre Redis
Préparation des Répertoires et Configurations
Créez des répertoires et des fichiers de configuration pour chaque instance (ports 7000 à 7005).
mkdir -p /opt/redis_cluster_data/{7000..7005}
# Modèle de configuration pour chaque nœud
# Répétez ce bloc pour les ports 7000 à 7005 en ajustant le port et les chemins.
cat > /opt/redis_cluster_data/7000/redis.conf <<EOF
port 7000
daemonize yes
pidfile /opt/redis_cluster_data/7000/redis_7000.pid
logfile "/opt/redis_cluster_data/7000/redis_7000.log"
dbfilename dump_7000.rdb
dir /opt/redis_cluster_data/7000
protected-mode no
cluster-enabled yes
cluster-config-file nodes-7000.conf # Chaque nœud doit avoir son propre fichier de config de cluster
cluster-node-timeout 5000
appendonly yes
EOF
Assurez-vous que chaque fichier redis.conf est correctement nommé et que les ports, pidfiles, logfiles, dbfilenames et cluster-config-file sont uniques pour chaque instance.
Démarrage des Nœuds
redis-server /opt/redis_cluster_data/7000/redis.conf
redis-server /opt/redis_cluster_data/7001/redis.conf
redis-server /opt/redis_cluster_data/7002/redis.conf
redis-server /opt/redis_cluster_data/7003/redis.conf
redis-server /opt/redis_cluster_data/7004/redis.conf
redis-server /opt/redis_cluster_data/7005/redis.conf
# Vérifiez que tous les nœuds sont démarrés
ps -ef | grep redis-server | grep cluster
Création du Cluster
Utilisez redis-trib.rb pour initialiser le cluster. L'option --replicas 1 indique que chaque maître aura une réplique.
/path/to/redis/src/redis-trib.rb create --replicas 1 \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
Confirmez la création en tapant yes.
Vérification de l'État du Cluster
redis-cli -p 7000 cluster nodes
redis-cli -c -p 7000 INFO cluster # Le -c est important pour le mode cluster
Pour tester, insérez et récupérez des données :
redis-cli -c -p 7000 SET maClef "une valeur"
redis-cli -c -p 7000 GET maClef
Le client devrait automatiquement se rediriger vers le nœud approprié.
Gestion des Nœuds du Cluster
Ajout d'un Nouveau Maître
Pour ajouter un nouveau nœud maître (ex: 7006), configurez-le et démarrez-le comme les autres. Ensuite, utilisez add-node :
redis-server /opt/redis_cluster_data/7006/redis.conf
/path/to/redis/src/redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
Le nouveau nœud est ajouté au cluster, mais il n'a pas encore de slots de hachage. Vous devez lui en attribuer via un reshard.
Re-partitionnement (Resharding) des Slots
Le re-partitionnement permet de déplacer des slots entre les nœuds. Pour attribuer des slots au nouveau nœud 7006 :
/path/to/redis/src/redis-trib.rb reshard 127.0.0.1:7000
# Nombre de slots à déplacer (ex: 1365 slots pour un nouveau maître)
How many slots do you want to move (from 1 to 16384)? 1365
# ID du nœud receveur (récupérez l'ID du nœud 7006 via 'cluster nodes')
What is the receiving node ID? <ID_DU_NOEUD_7006>
# Nœuds sources (tapez 'all' pour prendre des slots de tous les maîtres existants)
Source node #1: all
# Confirmez l'opération
Ajout d'une Réplique à un Maître Existant
Démarrez la nouvelle instance (ex: 7007). Ensuite, utilisez add-node --slave en spécifiant l'ID du maître qu'elle doit répliquer :
redis-server /opt/redis_cluster_data/7007/redis.conf
/path/to/redis/src/redis-trib.rb add-node --slave --master-id <ID_DU_NOEUD_7006> \
127.0.0.1:7007 127.0.0.1:7000
Suppression d'un Nœud
Pour supprimer un nœud maître, vous devez d'abord déplacer tous ses slots de hachage vers d'autres nœuds via un reshard. Ensuite, supprimez le nœud :
# Déplacer les slots du nœud à supprimer (ex: 7006) vers d'autres maîtres
/path/to/redis/src/redis-trib.rb reshard 127.0.0.1:7000
# ... (déplacer tous les slots du nœud 7006)
# Supprimer le nœud maître (ex: 7006)
/path/to/redis/src/redis-trib.rb del-node 127.0.0.1:7006 <ID_DU_NOEUD_7006>
# Supprimer un nœud réplique (ex: 7007)
/path/to/redis/src/redis-trib.rb del-node 127.0.0.1:7007 <ID_DU_NOEUD_7007>
Outils d'Administration Redis
Migration de Données avec redis-migrate-tool
Cet outil est utile pour migrer des données d'une instance Redis (ou cluster) à une autre.
# Installation
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool
autoreconf -fvi
./configure
make && make install
# Exemple de configuration (migration d'une instance 6379 vers un cluster à partir du nœud 7000)
cat > /tmp/migration_config.conf <<EOF
[source]
type: single
servers:
- 10.0.0.10:6379
[target]
type: redis cluster
servers:
- 10.0.0.10:7000
[common]
listen: 0.0.0.0:8889
source_safe: true
EOF
# Exécution de la migration
redis-migrate-tool -c /tmp/migration_config.conf
Analyse des Fichiers RDB avec redis-rdb-tools
Cet outil Python permet d'analyser le contenu d'un fichier RDB pour comprendre l'utilisation de la mémoire par les clés.
# Installation
pip install rdbtools # Ou installez depuis les sources GitHub
# Analyse et export au format CSV
rdb -c memory /opt/redis_cluster_data/7000/dump_7000.rdb -f /tmp/memory_report_7000.csv
# Tri par taille de clé
awk -F ',' '{print $4, $2, $3, $1}' /tmp/memory_report_7000.csv | sort -rh > /tmp/sorted_memory_report.txt
Intégration de Redis avec Python
Connexion à une Instance Unique
Le client Python redis-py est le plus courant.
import redis
# Connexion à une instance autonome
r_single = redis.StrictRedis(host='127.0.0.1', port=6379, db=0, password='mysecurepass')
# Opérations
r_single.set('produit_alpha', 'description_alpha')
print(r_single.get('produit_alpha'))
Connexion à un Cluster Sentinel
Pour un setup Maître-Réplique géré par Sentinel :
from redis.sentinel import Sentinel
sentinels = [('127.0.0.1', 26380)]
sentinel = Sentinel(sentinels, socket_timeout=0.1, password='mysecurepass')
# Obtenir une connexion au maître pour les écritures
master = sentinel.master_for('monmaitre', socket_timeout=0.1, password='mysecurepass')
master.set('config_clef', 'valeur_speciale')
# Obtenir une connexion à une réplique pour les lectures
replica = sentinel.slave_for('monmaitre', socket_timeout=0.1, password='mysecurepass')
print(replica.get('config_clef'))
Connexion à un Cluster Redis
Le client redis-py-cluster (ou redis.RedisCluster dans redis-py plus récent) est utilisé.
from rediscluster import RedisCluster # Ou from redis import RedisCluster pour redis-py >= 3.x
# Nœuds de démarrage du cluster
startup_nodes = [
{"host": "127.0.0.1", "port": "7000"},
{"host": "127.0.0.1", "port": "7001"},
# ... ajoutez tous les nœuds de votre cluster
]
# Connexion au cluster
# decode_responses=True est essentiel pour Python 3 afin d'obtenir des chaînes de caractères
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
# Opérations
rc.set("test_cluster_key", "valeur_cluster")
print(rc.get("test_cluster_key"))
Problématiques Courantes de Cache
Cache Penetration (Pénétration de Cache)
Se produit lorsqu'une application tente d'accéder à une clé qui n'existe ni dans le cache, ni dans la base de données. Des requêtes massives pour des clés inexistantes peuvent surcharger la base de données.
Solutions :
- Filtre de Bloom : Utiliser un filtre de Bloom pour stocker une représentation compacte de toutes les clés existantes. Si le filtre indique qu'une clé n'existe probablement pas, la requête peut être bloquée avant d'atteindre le cache ou la DB.
- Mise en Cache des Valeurs Nulles : Si une clé n'est pas trouvée dans la DB, stocker une valeur "nulle" ou un marqueur d'inexistence dans le cache pour une courte durée.
Cache Avalanche (Avalanche de Cache)
Survient lorsque de nombreuses clés de cache expirent simultanément, ou qu'un nœud de cache tombe en panne. Cela entraîne une cascade de requêtes vers la base de données sous-jacente, pouvant provoquer une panne.
Solutions :
- Temps d'Expiration Aléatoires : Ajouter un petit décalage aléatoire aux temps d'expiration des clés pour éviter des expirations groupées.
- Architecture Haute Disponibilité : Utiliser Redis Sentinel ou Redis Cluster pour minimiser l'impact des pannes de nœuds de cache.
- Pré-chargement du Cache : Recharger proactivement les données populaires dans le cache avant leur expiration.
Script de Gestion Redis
Un script Bash pour gérer les instances Redis de manière centralisée.
#!/bin/bash
# Fonction d'affichage de l'usage
afficher_usage() {
echo "Usage: $0 {demarrer|stopper|redemarrer|connexion|statut|journal} [PORT]"
echo " PORT est facultatif, par défaut 6379."
}
# Définition du port Redis
PORT_REDIS=${2:-6379} # Utilise le deuxième argument, sinon 6379
# Définition des chemins
DIR_BASE="/opt/redis_instances/redis_${PORT_REDIS}"
FICHIER_CONF="${DIR_BASE}/config/redis_${PORT_REDIS}.conf"
FICHIER_LOG="${DIR_BASE}/logs/redis_${PORT_REDIS}.log"
# Fonctions de commande
demarrer_instance() {
echo "Démarrage de l'instance Redis sur le port ${PORT_REDIS}..."
redis-server "$FICHIER_CONF"
statut_instance
}
stopper_instance() {
echo "Arrêt de l'instance Redis sur le port ${PORT_REDIS}..."
redis-cli -p "$PORT_REDIS" shutdown
statut_instance
}
connexion_instance() {
echo "Connexion à Redis sur le port ${PORT_REDIS}..."
redis-cli -p "$PORT_REDIS"
}
statut_instance() {
echo "Statut des processus Redis :"
ps -ef | grep "redis-server .*:${PORT_REDIS}" | grep -v grep
}
afficher_journal() {
echo "Affichage du journal pour l'instance Redis sur le port ${PORT_REDIS} (Ctrl+C pour quitter) :"
tail -f "$FICHIER_LOG"
}
# Logique principale du script
case "$1" in
demarrer)
demarrer_instance
;;
stopper)
stopper_instance
;;
redemarrer)
stopper_instance
demarrer_instance
;;
connexion)
connexion_instance
;;
statut)
statut_instance
;;
journal)
afficher_journal
;;
*)
afficher_usage
exit 1
;;
esac
Surveillance des Clés Expirables
Un défi opérationnel est de surveiller les clés avec un temps de vie (TTL) afin d'éviter des comportements inattendus, comme la perte prématurée de coupons ou de sessions. Il est crucial d'éviter des commandes comme KEYS * en production, car elles bloquent le serveur.
Approche Sûre : Utiliser la commande SCAN pour itérer sur les clés sans bloquer le serveur.
#!/bin/bash
FICHIER_LISTE_CLEFS="liste_cles_a_surveiller.txt"
FICHIER_SORTIE="cles_expirees_detectees.log"
REDIS_HOST="127.0.0.1"
REDIS_PORT="6379"
# Efface le fichier de sortie précédent
> "$FICHIER_SORTIE"
echo "Démarrage de la surveillance des clés expirables..."
# Lire chaque motif de clé à surveiller
while IFS= read -r motif_clef; do
echo "Recherche pour le motif: $motif_clef"
CURSEUR=0
# Itérer avec SCAN
while true; do
# Exécuter SCAN et capturer le curseur suivant et les clés
RESULTAT_SCAN=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" SCAN "$CURSEUR" MATCH "${motif_clef}*" COUNT 1000)
# Le curseur est sur la première ligne, les clés sur les lignes suivantes
NOUVEAU_CURSEUR=$(echo "$RESULTAT_SCAN" | head -n 1)
CLEFS_TROUVEES=$(echo "$RESULTAT_SCAN" | tail -n +2)
# Vérifier le TTL pour chaque clé trouvée
if [ -n "$CLEFS_TROUVEES" ]; then
echo "$CLEFS_TROUVEES" | while IFS= read -r clef_trouvee; do
TTL_CLEF=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" TTL "$clef_trouvee")
if [ "$TTL_CLEF" -eq -1 ]; then
echo "Clé persistante (TTL -1): $clef_trouvee (motif: $motif_clef)" | tee -a "$FICHIER_SORTIE"
elif [ "$TTL_CLEF" -eq -2 ]; then
echo "Clé non trouvée ou déjà expirée (TTL -2): $clef_trouvee (motif: $motif_clef)" | tee -a "$FICHIER_SORTIE"
elif [ "$TTL_CLEF" -lt 60 ]; then # Exemple: alerte si moins de 60 secondes
echo "Clé avec TTL court ($TTL_CLEF s): $clef_trouvee (motif: $motif_clef)" | tee -a "$FICHIER_SORTIE"
fi
done
fi
# Si le nouveau curseur est 0, nous avons parcouru toutes les clés
if [ "$NOUVEAU_CURSEUR" -eq 0 ]; then
break
fi
CURSEUR="$NOUVEAU_CURSEUR"
done
done < "$FICHIER_LISTE_CLEFS"
echo "Surveillance terminée. Résultats dans $FICHIER_SORTIE"
Ce script nécessite un fichier liste_cles_a_surveiller.txt contenant les motifs de clés (ex: session:*, coupon:*) à analyser, un par ligne.