Diagnostiquer et Résoudre les Requêtes Redis Lentes à l'Aide de la Commande SLOWLOG

Utilisez Redis SLOWLOG pour trouver les commandes lentes, ajuster les seuils, inspecter les clients et remplacer les modèles d'accès coûteux.

Diagnostiquer et Résoudre les Requêtes Redis Lentes à l'Aide de la Commande SLOWLOG

Redis est un magasin de données en mémoire incroyablement rapide, largement utilisé pour la mise en cache, l'analyse en temps réel, la gestion des sessions et le courtage de messages. Ses performances sont souvent critiques pour la réactivité des applications construites dessus. Cependant, même avec la vitesse de Redis, des commandes mal optimisées ou une charge inattendue peuvent entraîner des requêtes lentes, créant des goulots d'étranglement qui dégradent les performances globales de l'application.

Identifier la cause racine commence par SLOWLOG de Redis. Il enregistre les commandes dont le temps d'exécution côté serveur dépasse un seuil, ce qui vous aide à trouver les commandes coûteuses telles que KEYS, LRANGE large, HGETALL volumineux, ou les scripts Lua lents.

Comprendre la Fonctionnalité SLOWLOG de Redis

Le SLOWLOG est un système qui enregistre les requêtes dépassant un temps d'exécution spécifié. Il s'agit essentiellement d'un journal en mémoire des commandes qui ont pris plus de temps qu'un seuil configuré pour s'exécuter. Contrairement à un journal traditionnel basé sur des fichiers, SLOWLOG est stocké directement dans la mémoire de Redis, ce qui le rend rapide à accéder et à gérer sans encourir de surcharge d'E/S disque.

Chaque entrée contient un ID unique, un horodatage Unix, le temps d'exécution en microsecondes, les arguments de la commande et, dans les versions modernes de Redis, l'adresse et le nom du client lorsqu'ils sont disponibles. SLOWLOG mesure l'exécution des commandes à l'intérieur de Redis ; il n'inclut pas la latence réseau, l'attente côté client ou le temps passé en file d'attente avant que Redis ne commence à exécuter la commande.

Comment Fonctionne SLOWLOG : Paramètres de Configuration

Avant de pouvoir utiliser efficacement SLOWLOG, il est important de comprendre et de configurer ses deux paramètres principaux. Ces paramètres contrôlent ce qui est enregistré et combien d'entrées sont conservées.

slowlog-log-slower-than

Ce paramètre définit le seuil de temps d'exécution (en microsecondes) pour qu'une commande soit enregistrée. Seules les commandes qui prennent plus de temps que cette valeur spécifiée seront enregistrées dans le SLOWLOG. Définir cette valeur trop basse pourrait enregistrer trop de commandes, consommant potentiellement une mémoire significative et rendant l'analyse difficile. La définir trop haute pourrait vous faire manquer des requêtes vraiment lentes.

  • Valeur par défaut : 10000 (10 millisecondes)
  • Recommandation : Commencez avec la valeur par défaut et ajustez en fonction des exigences de performance de votre application. Pour les systèmes hautes performances, vous pourriez la réduire à 1000 microsecondes (1 milliseconde) ou même 100 microsecondes.
  • Valeur spéciale : La définir à 0 enregistrera chaque commande. La définir à une valeur négative désactivera complètement SLOWLOG.

Vous pouvez voir la valeur actuelle de ce paramètre :

redis-cli config get slowlog-log-slower-than

Pour définir une nouvelle valeur (par exemple, 5000 microsecondes, soit 5 millisecondes) :

redis-cli config set slowlog-log-slower-than 5000

Pour rendre ce changement permanent, vous devrez mettre à jour votre fichier redis.conf ou utiliser CONFIG REWRITE si votre version et configuration de Redis le supportent.

slowlog-max-len

Ce paramètre spécifie le nombre maximum d'entrées que Redis conservera dans le SLOWLOG. Lorsque le journal atteint sa longueur maximale, les nouvelles entrées entraîneront la suppression automatique des plus anciennes (FIFO - Premier entré, premier sorti).

  • Valeur par défaut : 128 entrées
  • Recommandation : La valeur par défaut est souvent trop petite pour les systèmes de production occupés. Envisagez de l'augmenter à 1024 ou même 4096 pour vous assurer de capturer suffisamment d'historique pour une analyse approfondie, en gardant à l'esprit les implications mémoire.

Vous pouvez voir la valeur actuelle :

redis-cli config get slowlog-max-len

Pour définir une nouvelle valeur (par exemple, 1024 entrées) :

redis-cli config set slowlog-max-len 1024

Encore une fois, n'oubliez pas de persister ce changement dans votre fichier redis.conf.

Récupération et Analyse des Entrées SLOWLOG

Une fois SLOWLOG configuré, vous pouvez interagir avec lui en utilisant un ensemble de commandes.

SLOWLOG GET

Cette commande est utilisée pour récupérer les entrées du SLOWLOG. Vous pouvez éventuellement spécifier un count pour récupérer un certain nombre des entrées les plus récentes.

  • SLOWLOG GET : Récupère toutes les entrées actuellement dans le journal.
  • SLOWLOG GET <count> : Récupère les <count> entrées les plus récentes.

Exemple :

# Récupérer les 10 entrées les plus récentes du journal lent
redis-cli slowlog get 10

Exemple de sortie (simplifié pour plus de clarté) :

1) 1) (integer) 12345        # ID unique pour l'entrée du journal
   2) (integer) 1678886400   # Horodatage Unix (par exemple, 15 mars 2023, 12:00:00 UTC)
   3) (integer) 25000        # Temps d'exécution en microsecondes (25 ms)
   4) 1) "LRANGE"           # La commande
      2) "mybiglist"       # Argument 1
      3) "0"               # Argument 2
      4) "-1"              # Argument 3
   5) "127.0.0.1:54321"  # IP et port du client
   6) "client-name-app" # Nom du client (si défini)
...

SLOWLOG LEN

Cette commande renvoie le nombre actuel d'entrées dans le SLOWLOG.

redis-cli slowlog len

Sortie :

(integer) 5

SLOWLOG RESET

Cette commande efface toutes les entrées du SLOWLOG. Cela est utile après avoir analysé les entrées existantes et vouloir recommencer avec un journal vierge pour capturer de nouvelles données de performance.

redis-cli slowlog reset

Sortie :

OK

Interprétation de la Sortie SLOWLOG

Chaque entrée fournit des informations critiques :

  1. ID unique : Un identifiant séquentiel. Utile pour suivre des événements spécifiques.
  2. Horodatage : Quand la commande a été exécutée. Aide à corréler les requêtes lentes avec les changements de déploiement de l'application ou les périodes de charge spécifiques.
  3. Temps d'exécution (microsecondes) : La métrique la plus importante. Cela vous indique exactement combien de temps la commande a pris pour se terminer. Des valeurs élevées indiquent un goulot d'étranglement potentiel.
  4. Commande et arguments : La commande Redis exacte et ses paramètres. Cela est crucial pour comprendre quelle opération était lente (par exemple, KEYS *, LRANGE 0 -1 sur une très grande liste, SORT sans LIMIT).
  5. Adresse du client : L'adresse IP et le port du client qui a émis la commande. Aide à retracer jusqu'à l'application ou le service source.
  6. Nom du client : Si votre application définit un CLIENT SETNAME (fortement recommandé pour une meilleure observabilité), cela fournit une couche supplémentaire de contexte, indiquant quelle partie de votre application a effectué la requête lente.

Exemple Pratique : Identifier une Commande Lente

Simulons une commande lente et voyons comment SLOWLOG la capture.

D'abord, définissez slowlog-log-slower-than à une valeur basse pour la démonstration, par exemple 1000 microsecondes (1 milliseconde) :

redis-cli config set slowlog-log-slower-than 1000

Ensuite, effectuez une opération connue pour être potentiellement lente si appliquée à un grand ensemble de données, comme KEYS * ou un LRANGE sur une liste avec de nombreux éléments.

Créons une grande liste :

for i in {1..100000}; do redis-cli LPUSH mybiglist $i; done

Maintenant, exécutez une commande LRANGE qui récupère tous les éléments de cette grande liste :

redis-cli LRANGE mybiglist 0 -1

Cette commande prendra probablement plus d'1 milliseconde.

Enfin, vérifiez le SLOWLOG :

redis-cli slowlog get 1

Vous devriez voir une sortie similaire à celle-ci (les valeurs varieront) :

1) 1) (integer) 12346
   2) (integer) 1678886450
   3) (integer) 15432 # C'est notre temps d'exécution lent en microsecondes
   4) 1) "LRANGE"
      2) "mybiglist"
      3) "0"
      4) "-1"
   5) "127.0.0.1:54322"
   6) ""

La sortie montre clairement la commande LRANGE mybiglist 0 -1, son temps d'exécution (15432 microsecondes ou 15,432 ms) et quand elle s'est produite. Cela nous indique immédiatement que la récupération d'une liste entière consomme un temps significatif.

Stratégies pour Résoudre les Requêtes Lentes

Une fois que vous avez identifié les requêtes lentes à l'aide de SLOWLOG, l'étape suivante consiste à les optimiser. Voici des stratégies courantes :

  1. Optimiser les Structures de Données et les Modèles d'Accès :

    • Évitez les commandes O(N) sur de grands ensembles de données : Les commandes comme LRANGE 0 -1 (obtenir tous les éléments), SMEMBERS (obtenir tous les membres d'un ensemble), HGETALL (obtenir tous les champs/valeurs d'un hachage), SORT (sans LIMIT) peuvent être lentes. Si vous devez traiter de grandes collections, envisagez d'itérer avec SCAN, SSCAN, HSCAN ou ZSCAN plutôt que de tout récupérer en une seule fois.
    • Utilisez des structures de données appropriées : Par exemple, si vous avez fréquemment besoin d'obtenir les attributs d'un objet, utilisez un Hash au lieu de stocker des clés individuelles pour chaque attribut.
    • Limitez les résultats : Pour les listes ou les ensembles triés, utilisez LRANGE <start> <end> ou ZRANGE <start> <end> avec des limites raisonnables au lieu de récupérer toute la structure.
  2. Pipelining : Au lieu d'envoyer les commandes une par une, regroupez plusieurs commandes en une seule requête en utilisant le pipelining. Cela réduit la surcharge du temps d'aller-retour réseau (RTT), ce qui peut accélérer considérablement les applications même si les commandes individuelles sont rapides.

    # Sans pipelining (plus lent en raison de multiples RTT)
    r.set('key1', 'value1')
    r.set('key2', 'value2')
    
    # Avec pipelining (plus rapide, un seul RTT)
    pipe = r.pipeline()
    pipe.set('key1', 'value1')
    pipe.set('key2', 'value2')
    pipe.execute()
    
  3. Scripting Lua (EVAL) : Pour les opérations complexes impliquant plusieurs commandes Redis qui doivent être exécutées de manière atomique ou avec un minimum de RTT, envisagez d'utiliser des scripts Lua. Les scripts sont exécutés directement sur le serveur Redis, réduisant la latence réseau et garantissant l'atomicité. Cependant, les scripts Lua de longue durée peuvent bloquer Redis, ils doivent donc être soigneusement optimisés.

  4. Évitez KEYS en Production : La commande KEYS est O(N) (où N est le nombre de clés dans la base de données) et peut bloquer le serveur Redis pendant une période prolongée, en particulier sur les grandes bases de données. Utilisez SCAN pour itérer sur les clés dans les environnements de production. SCAN fournit une fonctionnalité de type itérateur qui peut être mise en pause et reprise, évitant les longues opérations de blocage.

    # Mauvais en production
    redis-cli KEYS *
    
    # Bon en production pour l'itération
    redis-cli SCAN 0 MATCH user:* COUNT 100
    
  5. Regroupement de Connexions : Assurez-vous que votre application utilise un regroupement de connexions approprié pour gérer efficacement les connexions à Redis. Ouvrir et fermer des connexions pour chaque commande peut être gourmand en ressources.

  6. Partitionnement et Clustering : Si votre ensemble de données ou votre charge de travail dépasse ce qu'une seule instance Redis peut gérer, envisagez de partitionner vos données sur plusieurs instances Redis ou d'adopter Redis Cluster. Cela distribue la charge et les données, empêchant une seule instance de devenir un goulot d'étranglement.

  7. Réplicas de Lecture : Pour les charges de travail à forte lecture, déchargez les requêtes de lecture sur les réplicas de lecture Redis. Cela augmente le débit de lecture et réduit la charge sur l'instance principale, lui permettant de se concentrer sur les écritures.

Meilleures Pratiques pour l'Utilisation de SLOWLOG

  • Surveillance Régulière : Ne vous contentez pas de le configurer et de l'oublier. Vérifiez régulièrement les entrées SLOWLOG, en particulier après les déploiements ou pendant les périodes de pointe de charge.
  • Seuils Appropriés : Ajustez slowlog-log-slower-than en fonction de la latence acceptable de votre application. Ce qui est lent pour une application peut être normal pour une autre.
  • Longueur de Journal Suffisante : Définissez slowlog-max-len suffisamment grand pour conserver un historique significatif, mais pas trop grand pour consommer une mémoire excessive.
  • Effacement Périodique : Utilisez SLOWLOG RESET après avoir analysé les entrées pour obtenir des données fraîches, ou envisagez d'automatiser ce processus si vous intégrez SLOWLOG avec un système de surveillance.
  • Nommage des Clients : Utilisez CLIENT SETNAME <name> dans le code de votre application. Cela ajoute un contexte précieux aux entrées SLOWLOG, facilitant le traçage des commandes lentes vers des parties spécifiques de votre application.

À Retenir

Utilisez SLOWLOG pour attraper les commandes Redis coûteuses, puis corrigez le modèle d'accès au lieu de simplement augmenter les seuils. Si l'entrée lente montre une lecture large d'une énorme clé, paginez le résultat, scannez de manière incrémentielle, changez le modèle de données ou déplacez le travail lourd hors du chemin de la requête.