私たちの検索は物事を進めるときに流動的な状態にあるので、私は尋ねますが、インデックスに変更を加えるたびに(トークナイザーやフィルター、シャード/レプリカの数を変更する)、インデックス全体を吹き飛ばさなければなりませんすべてのRailsモデルをElasticsearchに再インデックスします...これは、すべてのレコードのインデックスを再作成するためにダウンタイムを考慮する必要があることを意味します。
これを行うための賢い方法はありますか?
@karmiが正しいと思います。ただし、もう少し簡単に説明しましょう。運用スキーマをいくつかの新しいプロパティまたは分析設定で時々アップグレードする必要がありました。最近、以下に説明するシナリオを使用して、ライブで一定の負荷のゼロダウンタイムインデックス移行を開始しました。リモートで実行できます。
手順は次のとおりです。
real1
とエイリアスreal_write
、real_read
を指し、real_write
にのみ書き込み、real_read
からのみ読み取ります_source
プロパティが利用可能です。選択した新しいマッピングと設定でreal2
インデックスを作成します。
次の一括クエリスイッチ書き込みエイリアスを使用します。
curl -XPOST 'http://esserver:9200/_aliases' -d '
{
"actions" : [
{ "remove" : { "index" : "real1", "alias" : "real_write" } },
{ "add" : { "index" : "real2", "alias" : "real_write" } }
]
}'
これはアトミック操作です。この時点から、real2
にはすべてのノードで新しいクライアントのデータが入力されます。読者はまだ_real1
経由で古い_real_read
を使用しています。これは最終的な一貫性です。
データはreal1
からreal2
に移行する必要がありますが、real2
の新しいドキュメントを古いエントリで上書きすることはできません。移行スクリプトは、bulk
操作でcreate
APIを使用する必要があります(index
またはupdate
ではありません)。シンプルなRuby script es-reindex を使用します。これはNice E.T.A.ステータスを持ちます:
$ Ruby es-reindex.rb http://esserver:9200/real1 http://esserver:9200/real2
UPDATE 2017スクリプトを使用する代わりに、新しい Reindex API を検討することもできます。競合レポートなどの興味深い機能がたくさんあります。
現在、real2
は最新であり、クライアントはそれに書き込みを行っていますが、real1
からは読み取り中です。リーダーエイリアスを更新しましょう。
curl -XPOST 'http://esserver:9200/_aliases' -d '
{
"actions" : [
{ "remove" : { "index" : "real1", "alias" : "real_read" } },
{ "add" : { "index" : "real2", "alias" : "real_read" } }
]
}'
書き込みと読み取りはreal2
に進みます。 ESクラスタからreal1
インデックスをバックアップおよび削除できます。
できた!
はい、ダウンタイムなしでデータのインデックスを再作成するよりスマートな方法があります。
まず、決して「最終」インデックス名を実際のインデックス名として使用しないでください。したがって、インデックスに「articles」という名前を付けたい場合は、その名前を物理インデックスとして使用せずに、「articles-2012-12-12」や「articles-A」、「articles」などのインデックスを作成します-1 "など.
次に、そのインデックスを指すエイリアス「alias」を作成します。アプリケーションはこのエイリアスを使用するため、インデックス名を手動で変更したり、アプリケーションを再起動したりする必要はありません。
第三に、データのインデックスを再作成する必要がある場合、またはインデックスを再作成する必要がある場合は、異なるインデックスに再インデックスします。たとえば、「articles-B」と指定します。
完了したら、エイリアスを新しいインデックスにポイントします。この方法では、ダウンタイムを最小限に抑えるだけでなく(安全なスナップショットもあります)、安全なスナップショットも得られます。インデックスを新しいインデックスに何らかの形で混乱させた場合、解決するまで古いインデックスに切り替えることができます。問題。
最近ダウンタイムなしで再インデックスを処理した方法に関するブログ投稿を書きました。そうするために必要なすべてのささいなことを理解するのに時間がかかります。お役に立てれば!
https://summera.github.io/infrastructure/2016/07/04/reindexing-elasticsearch.html
要約する:
新しいマッピングで新しいインデックスを作成します。これは、Elasticsearchの同じインスタンスでも、新しいインスタンスでも可能です。
インデックスの再作成中は、新しいインデックスと古いインデックスの両方を最新の状態に保ちたいと思います。書き込み操作の場合、これは、新しいインデックスと古いインデックスの両方でバックグラウンドワーカーに書き込み操作を送信することで実行できます。
レコードの削除と新しいインデックスへのインデックスの再作成の間には競合状態があるため、削除は少し複雑です。そのため、インデックスの再作成中に削除する必要があるレコードを追跡し、完了したらこれらを処理する必要があります。多数の削除を実行していない場合、別の方法は、インデックスの再作成中に削除の可能性を排除することです。
データの読み取りには スクロール検索 を使用し、挿入には bulk API を使用します。ステップ2の後、バックグラウンドで新しいインデックスおよび更新されたドキュメントを新しいインデックスに書き込むため、バルクAPIリクエストで新しいインデックス内の既存のドキュメントを更新しないようにする必要があります。
これは、バルクAPIリクエストに必要な操作がインデックスではなく作成であることを意味します。 documentation :「同じインデックスとタイプのドキュメントが既に存在する場合、作成は失敗しますが、インデックスは必要に応じてドキュメントを追加または置換します」ここでの主なポイントは、スクロールされた検索スナップショットの古いデータが新しいインデックスの新しいデータを上書きしないようにすることです。
このプロセスを支援する素晴らしいスクリプトがgithubにあります: es-reindex 。
インデックスの再作成が完了したら、検索を新しいインデックスに切り替えます。削除をオンに戻すか、新しいインデックスのキューに登録された削除ジョブを処理します。新しいインデックスの検索が最初は少し遅いことに気付くかもしれません。これは、ElasticsearchとJVMのウォームアップに時間が必要だからです。
必要なコード変更を実行して、アプリケーションが新しいインデックスの検索を開始するようにします。問題が発生してロールバックする必要がある場合に備えて、古いインデックスへの書き込みを続けることができます。これが不要だと思う場合は、書き込みを停止できます。
この時点で、新しいインデックスに完全に移行する必要があります。すべてが順調に進んでいる場合は、次のような必要なクリーンアップを実行します。
別のインデックスを作成し、そのインデックスにすべてのデータのインデックスを再作成し、インデックスの再作成が完了したら切り替えを行うこともできますか?