03 novembre 2015 Technique

Considérations sur les performances d'indexation dans Elasticsearch 2.0

Par Michael McCandless

Il y a un peu plus d'un an, j'ai expliqué comment maximiser la vitesse d'indexation avec Elasticsearch. Toutefois, beaucoup a changé depuis et je vais donc vous détailler les modifications qui ont un impact sur les performances d'indexation d'Elasticsearch 2.0.0.

small-auto-throttle.jpg 

La limite de stockage est désormais automatique  

Avant la version 2.0.0, Elasticsearch limitait les fusions en cours à une vitesse fixe (20 Mo/s par défaut). Souvent, cette vitesse était bien insuffisante et entraînait des retards dans les fusions et une limitation de l'index par la suite.

Depuis la version 2.0.0, Elasticsearch utilise une limitation adaptative des E/S : lorsque les fusions commencent à prendre du retard, le débit autorisé des E/S augmente. Il diminue lorsque les fusions sont traitées dans les temps. Cela signifie qu'une fusion volumineuse et soudaine associée à une faible vitesse d'indexation ne devrait pas saturer toutes les E/S du nœud. Elle aura ainsi un impact moindre sur les performances des recherches et indexations en cours. Lors d'une indexation importante, le nombre d'E/S de fusion autorisées augmentera en fonction des besoins.

C'est une excellente nouvelle !  Cela signifie que vous n'avez pas besoin de modifier les paramètres de limitation : conservez les valeurs par défaut.

Plusieurs chemins path.data

L'utilisation de plusieurs périphériques d'E/S (via la spécification de plusieurs chemins path.data ) pour stocker les shards sur votre nœud permet d'augmenter l'espace de stockage total et d'améliorer les performances d'E/S s'il s'agit du goulot d'étranglement de votre utilisation d'Elasticsearch.

La manière dont Elasticsearch répartit la charge d'E/S entre les différents chemins a été modifiée de manière significative. Auparavant, chaque fichier d'index de bas niveau était envoyé vers le chemin optimal (par défaut : le moins saturé). Désormais, cette répartition se fait par shard.  Lorsqu'un shard est attribué au nœud, le nœud choisit le chemin qui contiendra tous les fichiers de ce shard.  

Cette solution permet d'améliorer la résilience aux pannes des périphériques d'E/S : si l'un de vos périphériques d'E/S connaît une défaillance, vous ne perdrez que les shards qui s'y trouvaient, alors qu'auparavant, vous auriez perdu tous les shards dont au moins un fichier se trouvait sur ce périphérique (généralement, cela se traduisait par la perte de tous les shards du nœud).

Notez qu'un périphérique doté d'un RAID 0 logiciel n'est pas un bon choix, car vous perdrez tous les shards de ce nœud si l'un de ses périphériques connaît une défaillance. L'utilisation de plusieurs chemins path.data constitue donc la méthode recommandée.

Vous devez toujours disposer d'au moins une copie de vos index pour pouvoir récupérer les shards perdus sans perte de données.

L'optimisation de l'identifiant automatique a été supprimée

Auparavant, Elasticsearch optimisait la casse de l'identifiant automatique (lorsque vous ne fournissiez pas d'identifiant pour chaque document indexé) de sorte à utiliser des API Lucene d'ajout de suffixe directement. Toutefois, cette approche posait problème en cas d'erreur et nous l'avons donc supprimée.

Nous avons également grandement amélioré les performances de recherche des identifiants. Cette optimisation avait donc perdu de son importance. Nous avons ainsi pu supprimer tous les filtres Bloom, car ils consommaient une partie non négligeable de l'espace heap sans apporter de gain significatif en matière de performance dans la recherche d'identifiants.

Enfin, depuis la version 1.4.0, Elasticsearch utilise des identifiants Flake pour générer ses identifiants. Les performances de recherche sont ainsi meilleures qu'avec les anciens UUID.

Cela signifie que vous pouvez utiliser votre propre champ d'identifiant, sans impact négatif sur les performances maintenant que la gestion des identifiants automatiques a été supprimée. Toutefois, n'oubliez pas que les valeurs que vous choisissez pour les champs d'identifiant ont un impact sur les performances d'indexation.

Autres modifications...

En plus de ces modifications, de nombreuses autres ont été apportées à l'indexation dans la version 2.0, notamment : activation des Doc Values par défaut (au lieu d'utiliser des Field Data consommant des ressources CPU et de l'espace heap lors de la recherche), transformation de la dangereuse API delete-by-query centrale en un plugin sûr utilisé en surcouche de l'API d'indexation en bulk, exposition du contrôle sur une compression accrue des champs stockés pendant l'indexation, une meilleure compression des Doc Values rares et des normesréduction de l'espace heap requis lors de la fusion et diverses améliorations de la résilience, comme la détection de la corruption pré-existante d'un index lors de la fusion.

Pour voir les actions Lucene de bas niveau réalisées pendant l'indexation, ajoutez index.engine.lucene.iw: TRACE au fichier logging.ymlMais attention : cette modification va générer des résultats très volumineux!

Nos derniers graphiques des performances d'indexation montrent que nos valeurs par défaut évoluent dans la bonne direction : le nombre de documents par seconde et de segments pour les valeurs de la heap par défaut (4 Go) ont rejoint la ligne de performance rapide.