Optimisation de l'utilisation de la mémoire d'Elasticsearch pour des performances optimales

Maîtrisez la gestion de la mémoire d'Elasticsearch pour des performances maximales. Ce guide explore des techniques essentielles, y compris le dimensionnement du tas JVM, l'optimisation de l'indexation et de la recherche, l'exploitation de la mise en cache et le déploiement de disjoncteurs pour prévenir les erreurs OutOfMemory. Découvrez des stratégies pratiques pour garantir que votre cluster Elasticsearch reste stable et réactif, même sous forte charge.

Optimisation de l'utilisation de la mémoire d'Elasticsearch pour des performances optimales

Les problèmes de mémoire d'Elasticsearch se manifestent généralement par des recherches lentes, de longues pauses de garbage collection, des erreurs de disjoncteur ou des nœuds qui quittent le cluster. Optimiser l'utilisation de la mémoire d'Elasticsearch signifie équilibrer le tas JVM, le cache du système de fichiers, le nombre de shards, le comportement des requêtes et la pression d'indexation, plutôt que de simplement augmenter -Xmx.

L'objectif est simple : donner à Elasticsearch suffisamment de tas pour le travail du cluster et des requêtes tout en laissant suffisamment de RAM au système d'exploitation pour mettre en cache les fichiers de segments Lucene.

Comprendre les composants mémoire d'Elasticsearch

Elasticsearch utilise la mémoire dans deux grandes zones :

  • Tas JVM : Contient les métadonnées du cluster, les tampons d'indexation, les structures de requêtes, les fielddata lorsqu'ils sont activés, les caches et d'autres objets Java. Un tas trop petit provoque une pression et des déclenchements de disjoncteurs. Un tas trop grand peut allonger le garbage collection et priver le cache du système de fichiers.
  • Cache du système de fichiers et mémoire native : Le système d'exploitation met en cache les fichiers d'index Lucene en dehors du tas JVM. Elasticsearch utilise également la mémoire native pour la mise en réseau, les piles de threads et les fichiers mappés en mémoire.

Configurer la taille du tas JVM

Le dimensionnement du tas est le premier paramètre à vérifier. Elasticsearch utilise les fichiers jvm.options ou les options JVM spécifiques à l'environnement selon la façon dont il a été installé.

Définir Xms et Xmx ensemble

Définissez -Xms et -Xmx à la même valeur pour que la JVM ne redimensionne pas le tas pendant que le nœud est en cours d'exécution.

En règle générale, maintenez le tas à ou en dessous d'environ la moitié de la RAM physique et évitez de franchir le seuil du pointeur d'objet ordinaire compressé. En pratique, de nombreux nœuds de production restent en dessous d'environ 30 Go de tas, mais vous devez vérifier le seuil exact et les recommandations pour votre version d'Elasticsearch et de JVM.

Par exemple :

-Xms4g
-Xmx4g

Ceci définit le tas initial et maximum à 4 Go.

Surveiller l'utilisation du tas

Utilisez Kibana Stack Monitoring, les exportateurs Prometheus ou l'API Nodes Stats :

curl -X GET "localhost:9200/_nodes/stats/jvm?pretty"

Surveillez heap_used_percent, le temps de garbage collection, la pression de l'ancienne génération et les déclenchements de disjoncteurs. Un tas qui reste élevé pendant de longues périodes après le garbage collection signifie généralement que vous devez réduire les consommateurs de tas ou ajouter de la capacité.

Réduire la pression mémoire des shards et des requêtes

La disposition des index et la forme des requêtes ont un effet direct sur la mémoire.

Taille et nombre de shards

Chaque shard a des frais généraux. Trop de petits shards gaspillent le tas et ralentissent les opérations du cluster. De très gros shards peuvent rendre la récupération et la relocalisation difficiles. De nombreux clusters fonctionnent bien avec des tailles de shard de plusieurs dizaines de gigaoctets, mais les logs, les données de séries temporelles et les index à forte charge de recherche peuvent nécessiter des cibles différentes.

Par exemple, si un index de logs quotidiens crée 30 shards primaires pour 20 Go de données, vous payez des frais généraux pour de nombreux petits shards. Un ou deux primaires peuvent être plus faciles à gérer, selon la rétention et les modèles de requêtes.

Fusion de segments

Elasticsearch utilise des segments Lucene pour l'indexation. Les segments plus petits sont fusionnés en segments plus grands au fil du temps. Ce processus peut être gourmand en mémoire. Bien qu'Elasticsearch gère la fusion automatiquement, comprendre son impact peut être bénéfique, surtout lors de charges d'indexation lourdes.

Optimisation de la recherche et des agrégations

  • Utilisez des champs de type keyword pour les agrégations : Agrégez et triez sur les champs keyword, numériques, de date ou autres champs avec doc-values. Évitez d'activer fielddata sur les grands champs text sauf si vous comprenez le coût en tas.
  • Limitez les requêtes coûteuses : Les wildcards en tête et les requêtes d'expressions régulières larges peuvent être coûteuses. Préférez les champs structurés, les préfixes, les n-grammes ou les mappings search-as-you-type lorsque le cas d'utilisation nécessite une correspondance partielle.
  • Profilez les recherches lentes : Utilisez l'API de profilage dans un environnement de staging pour trouver les clauses de requête qui créent le plus de travail.

Utiliser les caches délibérément

Elasticsearch dispose de plusieurs caches. Ils aident pour les travaux répétés, mais ils consomment également de la mémoire.

  • Cache de requêtes de shard : Met en cache les résultats de recherche au niveau du shard pour les requêtes éligibles, souvent utile pour les requêtes d'agrégation répétées sur des données peu modifiées. Sa taille est contrôlée avec :

    indices.requests.cache.size: 5%
    

    Cet exemple définit la taille du cache de requêtes de shard à 5% du tas.

  • Cache de requêtes de nœud : Met en cache les résultats du contexte de filtre. Sa taille est contrôlée séparément :

    indices.queries.cache.size: 10%
    
  • Cache Fielddata : Consomme du tas et peut croître rapidement si vous activez fielddata sur les champs text. Préférez mapper correctement les champs plutôt que de compter sur un cache fielddata plus grand.

Prévenir les erreurs de mémoire insuffisante

Les erreurs de mémoire insuffisante sont généralement le résultat final d'une pression soutenue. La solution est rarement "augmenter toutes les limites".

Traiter le garbage collection comme un symptôme

Les versions récentes d'Elasticsearch choisissent les valeurs par défaut JVM prises en charge pour vous. Évitez le réglage personnalisé du garbage collector sauf si vous avez des conseils et des mesures spécifiques à la version. Les longues pauses indiquent généralement un oversharding, des agrégations coûteuses, des fielddata, une pression de tas trop élevée ou des nœuds insuffisants.

Les indicateurs clés des problèmes de GC incluent :

  • Temps de GC élevé.
  • Longues pauses stop-the-world.
  • Utilisation du tas qui remonte près de la limite après chaque collecte.
  • Erreurs OOM lors de grandes recherches, d'indexation par lots ou d'agrégations.

Respecter les disjoncteurs

Les disjoncteurs estiment l'utilisation de la mémoire et rejettent les opérations avant qu'elles ne puissent épuiser le nœud.

  • Disjoncteur Fielddata : Limite le tas utilisé pour les fielddata.
  • Disjoncteur de requêtes : Limite la mémoire utilisée pour terminer les structures de données de requêtes.
  • Disjoncteur parent : Suit les estimations combinées des disjoncteurs.

Consultez les statistiques des disjoncteurs avec :

curl -X GET "localhost:9200/_nodes/stats/breaker?pretty"

Vous pouvez modifier certains paramètres de disjoncteur via les paramètres du cluster, mais faites-le uniquement après avoir compris pourquoi le disjoncteur se déclenche. Un disjoncteur déclenché protège souvent le nœud d'une OOM.

Surveiller et alerter

Alertez sur :

  • L'utilisation du tas JVM après le garbage collection.
  • Le temps de garbage collection et les longues pauses.
  • Les déclenchements de disjoncteurs.
  • La pression d'indexation et les tâches rejetées des pools de threads.
  • La pression mémoire du système d'exploitation et l'utilisation du swap.
  • Le nombre de shards par nœud et les agrégations anormalement grandes.

Conclusion

Commencez par le dimensionnement du tas, puis examinez le nombre de shards, les mappings de champs, les grandes agrégations et les déclenchements répétés de disjoncteurs. Si votre nœud est toujours sous pression après le nettoyage, ajoutez de la capacité ou divisez les charges de travail au lieu de masquer les signes d'avertissement avec des limites plus grandes.