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?
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:
real1
et alias real_write
, real_read
le montrant,real_write
et lit uniquement à partir de real_read
,_source
La propriété du document est disponible.Créer real2
index avec la nouvelle cartographie et les nouveaux paramètres de votre choix.
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.
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.
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" } }
]
}'
Les écritures et les lectures vont à real2
. Vous pouvez sauvegarder et supprimer real1
index du cluster ES.
Terminé!
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.
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:
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.
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.
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 .
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.
À 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:
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?