Astuces et retour d’expérience sur Elasticsearch

De Fabien Gaujous dans Technique

19 nov 2013

La mise en place d’Elasticsearch comme énoncé dans l’article précédent nous a permis de creuser certains points essentiels d’Elasticsearch.
Voici donc un premier retour d’expérience avec la présentation d’astuces et des réponses à diverses questions que nous pouvons nous poser lorsque nous installons Elasticsearch pour la première fois.


Le mapping

Toujours créer un alias d’un index

Si vous voulez pouvoir facilement modifier le mapping sans arrêt de service, il faut créer un alias sur un index et l’utiliser pour accéder à cet index.
En effet, Il n’est pas possible de modifier un mapping à la volée (contrairement à ajouter des nouveaux champs, ou “upgrader” un champ en multi_field), pour cela, la façon de faire est la suivante :
1 – Créer un nouvel index “index2″ avec un même type mais un nouveau mapping associé
2 – Ré-indexer les données dans ce nouvel index (voir lien : http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/).

Voici la commande pour créer un alias nommé “aliaspublique” vers l’index “index1″

1
2
3
4
5
6
7
8
9
10
11
12
13
curl -XPOST http://localhost:9200/_aliases -d
'
{
"actions" : [
{
"add" : {
"index" : "index1",
"alias" : "aliaspublique"
}
}
]
}
'

Ne pas confondre les attributs “store” et “index” d’un champ

  • store peut prendre 2 valeurs : “yes”,”no” (par défaut “no”)
  • index peut prendre 3 valeurs : “analyzed”,”not_analyzed”,”no” (défaut “analyzed”)

Si vous connaissez déjà Lucene, vous connaissez déjà la réponse ;-)

Voici les explications :

  • “store” : “yes” indique que le champ est stocké et peut être récupéré après indexation du document
  • “store” : “no” indique que le champ ne sera pas stocké après indexation du document
  • “index” : “analyzed” indique que la valeur sera analysé par un analyzer (Gestion de la langue anglaise par défaut) avant d’être indexé
  • “index” : “not_analyzed” indique que la valeur telle quelle sera indexée. Par exemple, les espaces et stopswords sont ainsi gardés, ceci permet de recherche sur la chaine entière exacte.
  • “index” : “no” indique que la valeur ne sera pas indexée et ce champ ne sera pas pris en compte dans la recherche.

En jouant sur ces attributs et avec quelques astuces citées plus bas, vous pourrez définir au mieux votre mapping.

Utiliser les facettes sur des champs non analysés

Les recherches à facettes doivent se faire sur des champs non analysés “not_analyzed”.
En effet, les valeurs doivent être récupérées SANS traitement par l’analyzer, de plus, les facettes sur des champs notés “analyzed” demandent beaucoup de ressources mémoire qui peuvent vite conduire à des exceptions type OutOfMemory.
Pour ce faire, chaque champ utilisé pour des facettes, doit être défini en tant que type “multi_field” qui permet ainsi d’avoir à la fois la valeur analysée ainsi que la valeur non analysée ou “brute” que nous appelons souvent “untouched”.
Exemple de définition d’un champ famille de type multi_field :

1
2
3
4
5
6
7
8
9
10
11
"famille": {
        "properties": {
                "name": {
                    "type": "multi_field",
                        "fields" : {
                            "name" : {"type" : "string", "index" : "analyzed"},
                            "untouched" : {"type" : "string", "index" : "not_analyzed"}
                        }
                }    
            }
        }

Dans notre cas, la facette s’effectue sur le champ famille.name.untouched (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-multi-field-type.html)

Pour des documents JSON volumineux, préférez récupérer les champs notés “store” : “yes”

Lors de la recherche et de la récupération d’une entité, le champ _source permet de récupérer le document JSON complet qui a été envoyé au serveur.
Cependant, il est possible de définir les champs renvoyés par Elasticsearch afin de limiter le volume de données renvoyées.
Si les champs demandés ne sont pas définis “store” : “yes” , Elasticsearch parse le JSON contenu dans _source pour récupérer chacun des champs demandés.
Pour améliorer les performances dans des JSON volumineux, il faut définir ces champs “store” : “yes” , afin que Elasticsearch les récupère directement.

Configurer le bon analyzer

Pour ne pas avoir des résultats de recherche exubérants, il vaut mieux paramétrer le bon analyzer à la fois pour l’indexation et la recherche.
Voici ici le paramétrage pour un index de l’analyzer french disponible par défaut dans Elasticsearch et qui permet au moins de gérer les “stopwords” français.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"settings" : {
"index" : {
"number_of_shards" : 2,
"number_of_replicas" : 1,
            "analysis": {
                "analyzer" : {
                    "default": {
                        "type": "french"
                    }
                }
            }
        }    
    }
}

Si votre site gère du multi-langues, il exsite un plugin pour détecter la langue que nous n’avons pas testé :
elasticsearch-langdetect
Il sera souvent utile de créer un “custom” analyzer pour gérer la liste des tokenizers par exemple.

Astuces sur la création d’un cluster

Une fois toutes les configurations (mapping…) mises en place sur votre serveur de dev, et que tout fonctionne comme vous le souhaitez, la question qui se pose forcément : Comment configurer mon serveur de production (et avant de test ;-) ), afin d’assurer la haute disponibilité, des performances adéquates sur les recherches et la sauvegarde de mes données ?

Comme vous avez probablement du le lire au cours de vos recherches, Elasticsearch permet de traiter tous ces cas, mais il faut bien entendu le configurer comme il convient.
Elasticsearch permet de créer un cluster dans lequel plusieurs “nodes” sont démarrés et communiquent entre eux.

Donner un nom unique à votre cluster

Par exemple “cluster-recette” pour l’environnement de recette. Cela se configure dans elasticsearch.yml avec l’attribut “cluster.name”
En effet, Si vous gardez le nom du cluster par défaut ‘elasticsearch’ et que celui-ci est configuré en mode par défaut multicast (attribut discovery.zen.ping.multicast.enabled), des nodes non désirés vont pouvoir rejoindre le cluster…

Quel nombre de shards ou réplicats doit-on configurer pour un index ?

Le nombre de shards et de réplicats se configure dans le fichier elasticsearch.yml
Voici les valeurs par défaut :
index.number_of_replicas: 1
index.number_of_shards: 5

Existe-t-il une taille max pour un shard ?
Il existe une taille maximum par shard mais qui n’a pas une valeur définie. Ceci dépend du hardware, de la taille des docs …
La façon de faire est, sur un environnement ISO à la production, de charger sur un seul shard le plus possible de documents pour découvrir la taille maximum.

Existe-t-il un nombre de shards max ?
Je n’ai pas trouvé de valeur définie pour un nombre de shards maximum.
Cependant,chaque shard représente un certain nombre d’index Lucene et a ainsi besoin de ressources pour fonctionner.
Plus le nombre de shards est élevé, plus l’indexation et la recherche sera rapide puisqu’elle sera exécutée en parallèle sur tous les shards de l’index.
(Faire une recherche sur 1 index découpé en 5 shards est équivalent à en faire une sur 5 index composés d’un seul shard).
De plus, il est beaucoup plus simple et surtout plus rapide de bouger des shards d’un node à un autre au lieu de devoir découper un shard existant qui nécessite une réindexation de toutes les données de ce shard.
Pour finir, plus l’index est découpé en shards, plus la taille de l’index pourra être important.

Ainsi, pour trouver le nombre de shards adéquats, nous pouvons dire qu’il faut :
1 : Que le nombre de shards doit être plus élevé que le nombre de nodes.
2 : Diagnostiquer la taille maximum d’un shard et évaluer le volume de données possibles pour votre index.
3 : Faire des tests de montée en charge pour évaluer si le nombre de shards est adapté à votre utilisation.

A quoi sert un replicat ?

Un réplicat possède 2 fonctionnalités principales :

  1. Backup des données pour la haute disponibilité (HA). Si un node tombe, les données contenues dans les shards de ce node sont toujours disponible dans les replicats.
  2. Partage des ressources puisque ces réplicats sont aussi utilisés lors de la recherche. (scale search)

Dans un projet, contenant seulement 200 entités(nombre qui va très peu évoluer +-20), nous avons alors seulement défini 1 seul index avec :
2 shards
1 replicat
Le tout fonctionnant sur un cluster avec seulement 2 nodes. Nous avons alors d’excellentes performances avec peu de ressources tout en gardant la haute disponibilité et la réplication.

C’est quoi un master node ?

Un master node est identique à un autre node à part qu’il a été élu “master” car celui-ci est éligible (node.master: true par défaut dans elasticsearch.yml).
Un master node a pour responsabilité de gérer les suppressions et ajouts de node dans le cluster et de mettre à jour son état…et c’est tout ;-)

Pourquoi j’ai un shard noté “Unassigned” dans mon tableau de bord Head ?


Si vous avez installé Head pour gérer votre cluster alors vous pouvez voir des shards “unassigned”.
Ceci est dû au fait que le shard n’a pas trouvé de node adéquat dans lequel se positionner.
Par exemple, si un seul node est lancé et que le nombre de réplicats pour chaque shard est 1, le réplicat attendra qu’un 2eme node soit intégré au cluster pour l’assigner (puisque le replicat et le Shard original ne peuvent pas être sur le même node..)

Comment accéder à un cluster ?

Des librairies clientes permettent de dialoguer facilement avec Elasticsearch (Sur le port TCP 9300).
La librairie JAVA par exemple peut être configurée pour lancer de façon aléatoire (round-robin), les requêtes sur les différents nodes du cluster et de détecter la perte d’un des nodes.

Une autre façon d’effectuer du load balancing est de dédier un node pour faire du load balancing sur les autres nodes. Il ne stockera aucune donnée et ne pourra pas être élu en tant que master.
Celui-ci demandera donc que très peu de ressources pour fonctionner.
elasticsearch.yml :
node.master: false
node.data: false

Enfin, si vous déployez plusieurs nodes Elasticsearch sur le cloud Amazon, vous pouvez gérer le load balancing via ELB.

C’est fini pour aujourd’hui, nous espérons que cet article vous aidera à appréhender un certain nombre d’éléments pour configurer et utiliser Elasticsearch dans vos projets courants ou futurs !
N’oubliez pas notre prochain article sur la mise en place de Web services (JAVA) pour faciliter l’accès à Elasticsearch depuis des applications tierces.

Ressources


Site officiel :
http://www.elasticsearch.org
Stack Overflow :
elasticsearch-impact-of-setting-a-not-analyzed-field-as-storeyes
what-differents-between-master-node-gateway-and-other-node-gateway-in-elasticsearch
Informations sur les analyzers :
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis.html
quelques-bases-pour-preparer-une-indexation-dans-elasticsearch
Blog :
elasticsearch-five-things-i-was-doing-wrong
Videos
http://www.elasticsearch.org/videos/big-data-search-and-analytics/
Livre
under-the-hood

1 Réponse pour Astuces et retour d’expérience sur Elasticsearch

Avatar

khalid

mai 9th, 2014 à 19 h 55 min

Merci pour ce retour expérience fort utile, précis et concis.

Commentaire

7 + = dix

iMDEO recrute !

REJOIGNEZ-NOUS

A la recherche de nouveaux talents (développeurs web et mobile, chefs de projet,...)

Voir les annonces