Technique

Combien de partitions doit comporter mon cluster Elasticsearch ?

Remarque de l'éditeur : la règle générale qui consistait à avoir au maximum 20 partitions par Go de segment de mémoire a été déclarée obsolète à partir de la version 8.3. Ce blog a été mis à jour pour refléter la nouvelle recommandation.

Elasticsearch est une plateforme très polyvalente. Elle prend en charge de nombreux cas d'utilisation et apporte une grande flexibilité aux stratégies d'organisation et de réplication des données. Mais cette flexibilité est à double tranchant, car il est parfois difficile de déterminer en amont le meilleur moyen d'organiser vos données dans des index et des partitions, surtout si vous n'êtes pas familier avec la Suite Elastic. Si des choix moins optimaux ne vont pas nécessairement causer de problème au début, ils peuvent potentiellement engendrer des problèmes de performance avec l'augmentation des volumes de données au fil du temps. Plus le cluster contient des données, plus il sera difficile de résoudre le problème, car il est parfois nécessaire de réindexer de grandes quantités de données.

Lorsque nous croisons des utilisateurs avec des problèmes de performance, il n'est pas rare que la source de ce problème provienne de l'indexation des données et du nombre de partitions dans le cluster. C'est d'autant plus vrai dans les cas d'utilisation avec une architecture à plusieurs entités et/ou l'utilisation d'index temporels. Quand nous parlons de ce sujet avec des utilisateurs, que ce soit en personne lors d'événements ou de rencontres ou bien sur notre forum, les questions qui reviennent le plus sont : "Combien de partitions devrais-je avoir ?" et "Quelle taille doivent faire mes partitions ?"

Cet article a pour ambition de vous aider à répondre à ces questions et à fournir des recommandations utiles pour des cas d'utilisation comprenant l'utilisation d'index temporels (par exemple, logging ou analyses de sécurité) dans un seul et même endroit.

Qu'est-ce qu'une partition ?

Avant de commencer, nous devons définir quelques faits et termes qui seront nécessaires pour les sections suivantes.

Les données dans Elasticsearch sont organisées en index. Chaque index est constitué d'une ou plusieurs partitions. Chaque partition est une instance d'index Lucene, que vous pouvez imaginer comme un moteur de recherche autonome qui indexe et traite les recherches pour un sous-ensemble de données dans un cluster Elasticsearch.

Lorsque des données sont écrites dans des partitions, elles sont régulièrement publiées en nouveaux segments Lucene immuables sur le disque, et c'est à ce moment qu'elles deviennent disponibles pour les recherches. On appelle cela une actualisation. Son fonctionnement est expliqué de façon plus détaillée dans le document Elasticsearch: the Definitive Guide.

À mesure que le nombre de segments augmente, ces derniers sont régulièrement consolidés en de plus gros segments. On appelle ce processus la fusion. Étant donné que tous les segments sont immuables, cela signifie que l'espace disque utilisé va généralement varier pendant l'indexation, car de nouveaux segments fusionnés doivent être créés afin que ceux qu'ils remplacent puissent être supprimés. La fusion exige beaucoup de ressources, surtout à l'égard des opérations E/S sur le disque.

La partition est l'unité à laquelle Elasticsearch distribue des données à travers le cluster. La vitesse à laquelle Elasticsearch peut déplacer les partitions lors d'un rééquilibrage de données, par exemple suite à une défaillance, dépend de la taille et du nombre de partitions, ainsi que des performances du disque.

CONSEIL : évitez des partitions trop grandes, car ces dernières peuvent affecter négativement la capacité du cluster à se remettre d'une défaillance. Bien qu'il n'y ait pas de limite concrète à la taille d'une partition, on mentionne souvent une limite de 50 Go, car c'est ce qui semble fonctionner pour de nombreux cas d'utilisation.

Index par période de conservation

Étant donné que les segments sont immuables, la mise à jour d'un document implique que Elasticsearch trouve d'abord ce dernier et le désigne comme étant supprimé avant d'ajouter la nouvelle version. La suppression d'un document implique également que ce dernier soit retrouvé et désigné comme étant supprimé. Pour cette raison, les documents supprimés continueront d'occuper de l'espace disque et certaines ressources système jusqu'à ce qu'ils ne soient plus fusionnés, ce qui peut consommer de nombreuses ressources système.

Elasticsearch permet aux index complets d'être supprimés de façon très efficace directement depuis le système de fichiers, sans avoir à explicitement supprimer chaque enregistrement un à un. C'est de loin la méthode la plus efficace pour supprimer des données dans Elasticsearch.


CONSEIL : essayez d'utiliser les index temporels pour gérer la conservation des données dès que possible. Regroupez les données en index basés sur la période de conservation. Les index temporels permettent aussi de varier plus facilement le nombre de partitions et de réplicas principales au fil du temps, car ce paramètre peut être modifié afin de générer l'index suivant. Cela simplifie l'adaptation aux volumes de données et aux exigences variables.


Les index et les partitions peuvent-ils être utilisés librement ?

Pour chaque index Elasticsearch, les informations relatives au mapping et à l'état sont stockées dans l'état du cluster. Elles sont gardées en mémoire pour un accès rapide. L'utilisation d'un grand nombre d'index et de partitions dans un cluster peut donc entraîner un état de cluster volumineux, surtout si les mappings sont conséquents. Cela peut entraîner des longueurs au niveau de la mise à jour, étant donné que toutes les modifications doivent être effectuées dans un seul thread afin de garantir la cohérence avant que les changements ne soient distribués à travers le cluster.


CONSEIL : afin de réduire le nombre d'index et d'éviter les mappings conséquents et étendus, envisagez de stocker des données ayant une structure similaire dans le même index plutôt que de les diviser en index séparés en fonction de l'origine des données. Il est important de trouver un équilibre entre le nombre d'index et de partitions et la taille du mapping pour chaque index individuel. Étant donné que l'état du cluster est chargé dans la mémoire de chaque nœud (y compris les maîtres) et que la quantité de mémoire est directement proportionnelle au nombre d'index, de champs par index et de partitions, il est important de monitorer aussi l'utilisation de la mémoire sur les nœuds maîtres et de s'assurer qu'ils aient une taille appropriée. 


Chaque partition contient des données qui doivent être gardées en mémoire et qui utilisent de l'espace mémoire. Cela inclut les structures de données contenant des informations au niveau de la partition, mais aussi au niveau du segment afin de définir où se trouvent les données sur le disque. La taille de ces structures de données n'est pas fixe et varie selon le cas d'utilisation.

Cependant, une caractéristique importante de la surcharge liée aux segments est qu'elle n'est pas uniquement proportionnelle à la taille du segment. Cela signifie que des segments plus grands ont moins de surcharge par volume de données comparé aux segments plus petits. Cette différence peut être importante.

Afin de pouvoir stocker autant de données que possible par nœud, il est important de gérer l'utilisation de la mémoire et de réduire autant que possible la surcharge. Plus un nœud aura d'espace mémoire, plus il pourra supporter de données et de partitions.

Les index et les partitions ne sont donc pas sans coût pour le cluster, étant donné qu'il y a un certain degré de surcharge de ressources pour chaque index et partition.


CONSEIL : les petites partitions produisent des petits segments, ce qui augmente la surcharge. Efforcez-vous de maintenir la taille moyenne d'une partition entre au moins quelques Go et quelques dizaines de Go. Pour les cas d'utilisation avec des données temporelles, les partitions font généralement entre 20 Go et 40 Go.

CONSEIL : étant donné que la surcharge par partition dépend du nombre de segments et de leur taille, forcer la fusion de plus petits segments en de plus gros segments peut réduire la surcharge et améliorer les performances de recherche. Dans l'idéal, cette opération doit être effectuée une fois que les données ne sont plus écrites dans l'index. Sachez que cette opération est gourmande et devrait idéalement être effectuée hors des heures de pics d'indexation.

CONSEIL : le nombre de partitions pouvant être contenues dans un nœud sera proportionnel à la quantité de mémoire disponible, mais Elasticsearch n'applique pas de limite fixe. Une bonne règle générale est de s'assurer que le nombre de partitions par nœud reste en dessous de 20 par Go de mémoire configurée. Un nœud avec une mémoire de 30 Go devrait donc contenir un maximum de 600 partitions, mais plus vous êtes en dessous de la limite, mieux c'est. Cette opération permet généralement de préserver l'intégrité du cluster. Remarque de l'éditeur : À compter de la version 8.3, nous avons considérablement réduit la taille des segments utilisés pour les partitions. C'est pourquoi nous mettons à jour la règle générale présentée dans ce blog. Veuillez suivre le CONSEIL ci-dessous à compter de la version 8.3 d'Elasticsearch.)

NOUVEAU CONSEIL : prévoyez un segment de 1 Ko par champ par index sur les nœuds de données, plus les surcharges
L'utilisation précise des ressources d'un champ mappé dépend de son type. En règle générale, nous recommandons de prévoir une surcharge de segment d'environ 1 Ko par champ mappé par index détenu par chaque nœud de données. Vous devez aussi prévoir un segment ayant un volume suffisant par rapport à l'utilisation de référence d'Elasticsearch, ainsi que pour votre charge de travail (indexation, recherche, agrégation, etc.). Un segment supplémentaire de 0,5 Go suffira si votre charge de travail est raisonnable. Vous aurez peut-être besoin d'un moins grand volume si votre charge est légère. En revanche, prévoyez un plus gros volume si votre charge de travail est conséquente.

Par exemple, si un nœud de données détient des partitions de 1 000 index, contenant chacun 4 000 champs mappés, alors vous devrez prévoiror environ 1 000 x 4 000 x 1 Ko = 4 Go de segment pour les champs, auquel vient s'ajouter un segment de 0,5 Go supplémentaire pour la charge de travail et les autres surcharges. Par conséquent, ce nœud aura besoin d'une taille de segment d'au moins 4,5 Go.


Comment la taille d'une partition affecte-t-elle les performances ?

Dans Elasticsearch, chaque recherche est effectuée dans un seul thread par partition. En revanche, plusieurs partitions peuvent être traitées en parallèle, à l'instar de plusieurs recherches et agrégations dans la même partition.

Cela signifie que la latence de recherche minimum, sans mise en cache, dépendra des données, du type de recherche et de la taille de la partition. L'exécution de recherches sur de nombreuses petites partitions rendra l'opération par partition plus rapide, mais comme de nombreuses autres tâches doivent être mises en file d'attente et traitées en séquence, cela ne va pas nécessairement être plus rapide que des recherches qui visent un petit nombre de grandes partitions. Avoir de nombreuses petites partitions peut également réduire le débit des recherches en cas de recherches simultanées.


CONSEIL : le meilleur moyen de déterminer la taille de partition maximum d'un point de vue des performances de recherche est de procéder à une évaluation comparative avec des données et des recherches réalistes. Il faut toujours procéder à une évaluation avec une charge de recherche et d'indexation représentative de ce que le nœud aurait à gérer en production, car l'optimisation pour une seule recherche peut donner des résultats erronés.


Comment gérer la taille des partitions ?

Si vous utilisez des index temporels, chaque index a généralement été associé à une période fixe. Les index quotidiens sont très courants et sont souvent utilisés pour conserver des données à courte durée de conservation ou de grands volumes quotidiens. Ils permettent de gérer la période de conservation avec une bonne granularité et facilitent l'ajustement quotidien en fonction de l'évolution des volumes. Les données avec une période de conservation plus longue, surtout si les volumes quotidiens ne justifient pas l'utilisation d'index quotidiens, utilisent souvent des index hebdomadaires ou mensuels afin de maintenir la taille de la partition. Ce procédé réduit le nombre d'index et de partitions devant être stockés dans le cluster au fil du temps.


CONSEIL : si vous utilisez des index temporels qui couvrent une période fixe, ajustez la période couverte par chaque index en fonction de la période de conservation et des volumes de données prévus afin d'atteindre la taille de partition désirée.


Les index temporels avec un intervalle de temps fixe fonctionnent bien lorsque les volumes de données sont raisonnablement prévisibles et changent lentement. Si le taux d'indexation varie rapidement, il est très difficile de conserver une taille de partition cible uniforme.

Afin de pouvoir mieux gérer ce type de scénarios, des API de substitution et de réduction ont été créées. Ces dernières apportent une grande flexibilité à la gestion des index et des partitions, particulièrement celle des index temporels.

L'API de substitution d'index permet de préciser le nombre de documents qu'un index devrait contenir et/ou la période maximum où les documents devraient y être écrits. Une fois que l'un de ces critères a été dépassé, Elasticsearch peut déclencher la création d'un nouvel index pour écrire sans période d'indisponibilité. Plutôt que d'avoir un index par période spécifique, il est désormais possible de passer à un nouvel index avec une taille spécifique, ce qui permet d'obtenir plus facilement une partition de taille égale pour chaque index.

Pour les cas où les données pourraient être mises à jour, il n'y a plus de lien distinct entre l'horodatage de l'évènement et l'index dans lequel il se trouve quand cette API est utilisée. Cette particularité peut affecter considérablement l'efficacité des mises à jour, puisque chacune d'elles doit être précédée d'une recherche.


CONSEIL : si vous avez des données immuables temporelles dont les volumes peuvent varier considérablement au fil du temps, envisagez d'utiliser l'API de substitution d'index pour obtenir une taille de partition cible optimale en variant la période couverte par chaque index en temps réel. Ce procédé offre une grande flexibilité et permet d'éviter d'avoir des partitions trop grandes ou trop petites lorsque les volumes sont imprévisibles.


L'API de réduction d'index permet de réduire un index existant dans un nouvel index avec moins de partitions principales. Si l'on veut une répartition égale de partitions sur l'ensemble des nœuds au cours de l'indexation, mais que cela produira des partitions trop petites, cette API peut servir à réduire le nombre de partitions principales une fois l'indexation terminée. Cela produira des partitions plus grandes et mieux adaptées au stockage de données à long terme.


CONSEIL : si vous avez besoin que chaque index couvre une période spécifique, mais que vous voulez tout de même pouvoir répartir l'indexation sur un grand nombre de nœuds, envisagez d'utiliser l'API de réduction pour réduire le nombre de partitions principales une fois l'indexation terminée. Cette API peut également servir à réduire le nombre de partitions si vous avez initialement configuré trop de partitions.


Conclusions

Cet article a fourni des astuces et des recommandations utiles sur la gestion optimale des données dans Elasticsearch. Si vous voulez en apprendre davantage, le document "Elasticsearch: the definitive guide" contient une section dédiée à la conception à grande échelle, qui, même si elle est un peu vieille, vaut le coup d'œil.

De nombreuses décisions à propos de la meilleure façon de distribuer vos données sur l'ensemble des index et partitions dépendront des détails des cas d'utilisation, et il peut parfois être difficile de déterminer comment appliquer au mieux les conseils à disposition. Pour des conseils plus détaillés et personnels, vous pouvez travailler avec nous en souscrivant à un abonnement et laisser nos équipes de support technique et consulting donner un coup d'accélérateur à votre projet. Si vous ne voyez pas d'inconvénient à discuter de votre cas d'utilisation publiquement, vous pouvez aussi obtenir de l'aide auprès de notre communauté et via notre forum public.


Cet article a été initialement publié le 18 septembre 2017. Il a été mis à jour le 6 juillet 2022.