web-dev-qa-db-fra.com

Existe-t-il un moyen plus intelligent de réindexer elasticsearch?

Je demande parce que notre recherche est dans un état de flux au fur et à mesure que nous travaillons, mais chaque fois que nous apportons une modification à l'index (changement de jeton ou de filtre, ou nombre de fragments/répliques), nous devons souffler tout l'index et réindexer tous nos modèles Rails dans Elasticsearch ... cela signifie que nous devons prendre en compte les temps d'arrêt pour réindexer tous nos enregistrements.

Y a-t-il une façon plus intelligente de faire cela que je ne connais pas?

43
concept47

Je pense que @karmi fait bien les choses. Mais permettez-moi de l'expliquer un peu plus simplement. Je devais parfois mettre à niveau le schéma de production avec de nouvelles propriétés ou de nouveaux paramètres d'analyse. J'ai récemment commencé à utiliser le scénario décrit ci-dessous pour effectuer des migrations d'index en direct, à charge constante et sans interruption. Vous pouvez le faire à distance.

Voici les étapes:

Hypothèses:

  • Vous avez l'index real1 et alias real_write, real_read le montrant,
  • le client écrit uniquement sur real_write et lit uniquement à partir de real_read,
  • _source La propriété du document est disponible.

1. Nouvel indice

Créer real2 index avec la nouvelle cartographie et les nouveaux paramètres de votre choix.

2. Commutateur d'alias d'écrivain

Utilisation de l'alias d'écriture du commutateur de requête en bloc suivant.

curl -XPOST 'http://esserver:9200/_aliases' -d '
{
    "actions" : [
        { "remove" : { "index" : "real1", "alias" : "real_write" } },
        { "add" : { "index" : "real2", "alias" : "real_write" } }
    ]
}'

Il s'agit d'une opération atomique. A partir de ce moment real2 est rempli avec les données du nouveau client sur tous les nœuds. Les lecteurs utilisent toujours l'ancien real1 via real_read. C'est une cohérence éventuelle.

3. Ancienne migration des données

Les données doivent être migrées depuis real1 à real2, cependant de nouveaux documents dans real2 ne peut pas être remplacé par les anciennes entrées. Le script de migration doit utiliser l'API bulk avec l'opération create (pas index ou update). J'utilise un simple Ruby script es-reindex qui a le statut Nice E.T.A.:

$ Ruby es-reindex.rb http://esserver:9200/real1 http://esserver:9200/real2

MISE À JOUR 2017 Vous pouvez envisager une nouvelle API Reindex au lieu d'utiliser le script. Il a beaucoup de fonctionnalités intéressantes comme les rapports de conflits, etc.

4. Commutateur d'alias de lecteur

Maintenant real2 est à jour et les clients y écrivent, mais ils lisent toujours à partir de real1. Mettons à jour l'alias du lecteur:

curl -XPOST 'http://esserver:9200/_aliases' -d '
{
    "actions" : [
        { "remove" : { "index" : "real1", "alias" : "real_read" } },
        { "add" : { "index" : "real2", "alias" : "real_read" } }
    ]
}'

5. Sauvegarder et supprimer l'ancien index

Les écritures et les lectures vont à real2. Vous pouvez sauvegarder et supprimer real1 index du cluster ES.

Terminé!

70
gertas

Oui, il existe des moyens plus intelligents de réindexer vos données sans interruption.

Tout d'abord, n'utilisez jamais le nom d'index "final" comme votre vrai nom d'index. Donc, si vous souhaitez nommer votre index "articles", n'utilisez pas ce nom comme index physique, mais créez un index tel que "articles-2012-12-12" ou "articles-A", "articles -1 ", etc.

Deuxièmement, créez un alias "alias" pointant vers cet index. Votre application utilisera alors cet alias, vous n'aurez donc jamais besoin de modifier manuellement le nom de l'index, de redémarrer l'application, etc.

Troisièmement, lorsque vous voulez ou devez ré-indexer les données, ré-indexez-les dans un index différent, disons "articles-B" - tous les outils de l'indexation de la chaîne d'outils d'indexation de Tire vous soutiennent ici.

Lorsque vous avez terminé, pointez l'alias vers le nouvel index. De cette façon, non seulement vous minimisez les temps d'arrêt (il n'y en a pas), vous avez également un instantané sûr: si vous gâchez l'indexation dans le nouvel index, vous pouvez simplement revenir à l'ancien, jusqu'à ce que vous résolviez le problème. problème.

30
karmi

J'ai récemment rédigé un article de blog sur la façon dont j'ai géré la réindexation sans interruption. Prend un certain temps pour comprendre toutes les petites choses qui doivent être en place pour le faire. J'espère que cela t'aides!

https://summera.github.io/infrastructure/2016/07/04/reindexing-elasticsearch.html

Résumer:

Étape 1: préparer un nouvel index

Créez votre nouvel index avec votre nouveau mappage. Cela peut être sur la même instance d'Elasticsearch ou sur une toute nouvelle instance.

Étape 2: Gardez les index à jour

Pendant que vous réindexez, vous voulez garder à jour vos nouveaux et anciens index. Pour une opération d'écriture, cela peut être fait en envoyant l'opération d'écriture à un travailleur en arrière-plan sur le nouvel et l'ancien index.

Les suppressions sont un peu plus délicates car il existe une condition de concurrence entre la suppression et la réindexation de l'enregistrement dans le nouvel index. Donc, vous voudrez garder une trace des enregistrements qui doivent être supprimés pendant votre réindexation et les traiter lorsque vous avez terminé. Si vous n'effectuez pas beaucoup de suppressions, une autre façon serait d'éliminer la possibilité d'une suppression pendant votre réindexation.

Étape 3: effectuer une réindexation

Vous voudrez utiliser un recherche par défilement pour lire les données et API en vrac pour l'insertion. Étant donné qu'après l'étape 2, vous allez écrire des documents nouveaux et mis à jour dans le nouvel index en arrière-plan, vous devez vous assurer de ne PAS mettre à jour les documents existants dans le nouvel index avec vos demandes d'API en bloc.

Cela signifie que l'opération que vous souhaitez pour vos demandes d'API en bloc est de créer, pas d'indexer. D'après la documentation : "create échouera si un document avec le même index et le même type existe déjà, alors que index ajoutera ou remplacera un document si nécessaire". Le point principal ici est que vous ne voulez pas que les anciennes données de l'instantané de recherche avec défilement écrasent les nouvelles données dans le nouvel index.

Il existe un excellent script sur github pour vous aider dans ce processus: es-reindex .

Étape 4: basculez

Une fois que vous avez fini de réindexer, il est temps de basculer votre recherche vers le nouvel index. Vous souhaiterez réactiver les suppressions ou traiter les tâches de suppression mises en file d'attente pour le nouvel index. Vous remarquerez peut-être que la recherche du nouvel index est un peu lente au début. En effet, Elasticsearch et la JVM ont besoin de temps pour se réchauffer.

Effectuez toutes les modifications de code dont vous avez besoin pour que votre application commence à rechercher le nouvel index. Vous pouvez continuer à écrire dans l'ancien index si vous rencontrez des problèmes et devez annuler. Si vous pensez que cela n'est pas nécessaire, vous pouvez arrêter d'y écrire.

Étape 5: nettoyer

À ce stade, vous devez être complètement transféré vers le nouvel index. Si tout se passe bien, effectuez tout nettoyage nécessaire tel que:

  • Supprimez l'ancien hôte d'index s'il est différent du nouveau
  • Supprimer le code de sérialisation lié à votre ancien index
3
Ari

Peut-être créer un autre index et réindexer toutes les données sur celui-ci, puis effectuer le basculement une fois la réindexation terminée?

2
Emil Hajric