Application Java et indexation dans ElasticSearch

Bonjour,

Nous travaillons sur une application web (avec un back Java) qui utilise ElasticSearch pour indexer des données.

Nous avons fait le choix d'utiliser Logstash pour :

  • Lire les données directement dans la base de données via le plugin jdbc
  • Ecrire ces données dans ElasticSearch

Première question que l'on se pose :

  • Est-ce une manière correcte d'utiliser Logstash et ElasticSearch ?
    Nous remettons en question ce choix suite à la non possibilité de mettre en place un cluster de Logstash pour le moment.

Suite à cette interrogation, nous avons envisagé de déléguer l'indexation des données à l'application Java directement et de supprimer Logstash. Néanmoins, cette architecture nous pose quelques questions :

  • Comment faire, pour appliquer des modifications sur les configurations de templates et/ou mapping de nos index, sans perdre de données ? Les modifications étant à appliquer sur une application qui reste utilisable lors des livraisons.
  • Si l'index est supprimé puis recréé, la réindexation des données via Java est-elle plus lourde et plus longue que via Logstash ?

Merci d'avance pour vos réponses.

Bonjour Amandine,

J'ai justement un talk (mon talk favori à vrai dire) qui parle de ce sujet. En voici un résumé sous forme de blog post: https://david.pilato.fr/blog/2015-05-09-advanced-search-for-your-legacy-application/

Quelques commentaires et réponses:

Est-ce une manière correcte d'utiliser Logstash et Elasticsearch ?

On dit Elasticsearch et non ElasticSearch :wink:
Oui. C'est correct.

Mais ce n'est pas ma méthode préférée. Je préfère de loin modifier l'application si cela est possible pour indexer directement dans elasticsearch dès qu'une entité métier est créée/mise à jour/supprimée dans la base de données.

Autre possibilité, écrire dans un système de messagerie asynchrone genre RabbitMQ, Kafka, Redis et faire consommer ça par un LS par exemple.
Mon projet de démo est ici:

Comment faire, pour appliquer des modifications sur les configurations de templates et/ou mapping de nos index, sans perdre de données ? Les modifications étant à appliquer sur une application qui reste utilisable lors des livraisons.

Vaste sujet (que ce soit avec Logstash ou pas d'ailleurs). Idéalement, quand tu as des changements de schéma de ton application, tu peux:

  • Soit laisser elasticsearch créer les nouveaux champs automatiquement. Avec un nommage propre des champs, tu peux utiliser des index templates avec du dynamic mapping pour faire ça de façon propre.
  • Soit créer un nouvel index systématiquement, réindexer toutes les données (soit par relecture de la base, soit en utilisant l'API reindex - mais je suppose inutile dans ce cas car les nouveaux champs n'existaient pas dans elasticsearch précédemment). Puis en utilisant un alias, switcher l'alias du vieil index vers le nouveau quand l'opération est finie. Puis détruire le vieil index.
  • Soit un mix des deux, suivant le cas.

D'une manière générale, je conseille de mettre systématiquement un alias pour ton/tes index.

Si l'index est supprimé puis recréé, la réindexation des données via Java est-elle plus lourde et plus longue que via Logstash ?

En général, ce c'est pas la question essentielle. D'abord la lenteur vient en général de la lecture de la base de données source. Ensuite les données sont souvent bien complexes et sont dispersées dans plusieurs tables. Faire des joins dans tous les sens pour ramener un objet métier complexe est assez difficile à mon avis à faire avec Logstash (bien que le nouveau jdbc filter pourrait aider maintenant). Si tu as déjà des objets métiers capables d'être générés à partir d'une base de données, il est assez simple de les transformer en JSON et de les envoyer vers elasticsearch.

Je préfère donc, sauf cas simple, l'approche pure Java. Qui du coup, comme plus optimisée car exactement faite à façon sera peut-être plus rapide...

Enfin, si tu utilises Hibernate, sache que Hibernate Search propose une intégration assez sympa avec Elasticsearch.

En espérant que ça t'aide.

Bonjour,

Merci beaucoup pour cette réponse détaillée ! :slight_smile:
Cela nous aide effectivement dans notre réflexion.

Concernant le mapping dynamique, imaginons que nous avons déjà des documents indexés :
Si on change un attribut d'un objet java de "prenomm" à "prénom" :

  • Comment gérer ce genre de modification ?
  • Est-ce que seuls les nouveaux docs auront un champ "prénom" ?
  • Est-ce que les documents déjà indexés auront à la fois "prenomm" et "prénom" ?

Pour la réindexation avec lecture en base de données en Java, est-ce que vous auriez des astuces ou des bonnes pratiques à nous donner pour le faire efficacement ?

Merci pour le conseil sur Hibernate Search. Nous utilisons Spring Boot 2 et Elasticsearch 6.
Nous allons essayer le plugin Spring Data Elasticsearch quand il sera prêt pour Elastichsearch 6.

Merci d'avance pour vos réponses.

Si on change un attribut d'un objet java de f1 à f2

En supposant que tu changes l'attribut puis que tu n'envoies vers elasticsearch que les modifications (les nouveaux objets et les objets mis à jour après cette date), seuls ces derniers auront le nouveau champ. L'ancien reste dans elasticsearch, inchangé.

En gros tu auras des documents:

{
  "f1": "foo"
}

et des documents:

{
  "f2": "foo"
}

Dans ce cas, il faudra que tu cherches sur les deux champs. Cela peut-être acceptable suivant le cas d'utilisation.

Si tu choisis de tout réindexer depuis le début dans le même index.
Tu n'auras donc que des documents:

{
  "f2": "foo"
}

Mais le mapping conservera le champ f1 devenu inutile du coup.
A noter que cette méthode est assez coûteuse en terme d'IO disque. Car chaque fois que tu fais un UPDATE, tu fais en réalité un DELETE et un INSERT.
Or le DELETE n'efface pas de la donnée sur disque mais ajoute une information disant en gros que tu supprimes des documents. Pour schématiser, plus tu effaces, plus tu consommes de l'espace disque. A un certain moment, elasticsearch fera du "merge des segments" et en profitera pour effectivement supprimer les données non valides. Mais ce merge produit beaucoup d'IO car il faut réécrire des tas de choses.

Bref, dans ce cas, il vaut mieux tout reindexer dans un index neuf et vide. Et utiliser la technique d'alias dont j'ai déjà parlé.

(Parenthèse "commerciale")
Enfin, je t'invite ainsi que ton équipe à aller aux formations que nous dispensons sur Paris. Elles sont en français et pourraient être super utiles pour vous faire gagner du temps au final. Les prochaines ne sont pas encore annoncées mais devraient j'espère avoir lieu courant Avril: https://training.elastic.co/
(Fin de la parenthèse).

Très bien, merci beaucoup ! :smile:

Nous allons partir sur la création d'un nouvel index et une réindexation complète à chaque modification alors. C'est noté pour la technique des alias.

Je me permets de relancer le sujet en ajoutant une information supplémentaire.

L'approche de l'indexation directe via Java est-elle encore la meilleure approche lorsque l'on se situe dans un contexte de micro-services ? Sachant que tous les micro-services écrivent dans un même cluster Elasticsearch.

Merci d'avance pour votre réponse.

L'approche de l'indexation directe via Java est-elle encore la meilleure approche lorsque l'on se situe dans un contexte de micro-services ?

Ca change ou changerait quoi en fait ?

Chaque micro-service doit porter de l'intelligence sur l'indexation des données, ajoutant ainsi une forte dépendance à Elasticsearch. Avec une indexation via Logstash, on sépare totalement l'indexation des données du micro-service, donc on a un couplage moins fort. Est-ce que sur du long terme, pour une application constituée de plusieurs micro-services, ce n'est pas plus simple à maintenir via Logstash ?

D'un autre côté, Logstash serait-il capable de supporter une dizaine de pipelines, sachant que chaque pipeline effectuerait une requête en base de données de manière périodique ? Les échanges discontinus entre la base de données et Logstash peuvent-il fragiliser la stabilité de Logstash ?

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.

Désolé pour le délai.

Logstash serait-il capable de supporter une dizaine de pipelines, sachant que chaque pipeline effectuerait une requête en base de données de manière périodique ?

Oui je pense que ça ne devrait pas poser de problèmes. @colinsurprenant pourrait confirmer/infirmer je pense.

Les échanges discontinus entre la base de données et Logstash peuvent-il fragiliser la stabilité de Logstash ?

Non je ne pense pas.

En effet pas de probème - chaque pipeline fonctionne de façon indépendante.