ElasticSearch の実装原理と基礎となる実装、転置インデックスとは何ですか、また一般的に使用されるトークナイザーとは何ですか?

1. はじめに

Elasticsearch は、 Luceneに基づく分散検索サーバーですRESTful Web インターフェイスに基づいた分散マルチユーザー対応の全文検索エンジンを提供します。Java 言語で開発され、Apache ライセンスの条件に基づいてオープン ソースとしてリリースされた Elasticsearch は、人気のあるエンタープライズ グレードの検索エンジンです。Elasticsearch はクラウド コンピューティングで使用され、安定性、信頼性、高速性、そしてインストールと使用が簡単なリアルタイム検索を実現します。公式クライアントは、Java、.NET (C#)、PHP、Python、Apache Groovy、Ruby、その他多くの言語で利用できます。DB-Engines のランキングによると、Elasticsearch が最も人気のあるエンタープライズ検索エンジンであり、続いて同じく Lucene ベースの Apache Solr (最新バージョンは Elastic 7.11 に更新されました) です。

ElasticSearch には(全文検索機能に加えて)次の機能もあります。
  • 分散型リアルタイム ファイル ストレージ。各フィールドにはインデックスが付けられ、検索できるようになります。
  • リアルタイム分析のための分散型検索エンジン。
  • 数百台のサーバーに拡張でき、PB レベルの構造化データまたは非構造化データを処理できます。
次に、基礎となるインデックス構造は次のとおりです。

ES はドキュメント指向であり、すべてのテキスト データはドキュメントの形式で ES に保存されます。データは JSON 形式で保存され、一意の文書データは _index、_type、_id によって識別されます。ドキュメントには多くのフィールドが存在する可能性があり、各フィールドはさまざまなデータ情報を記述するための固定データ型です。

_index:1 つ以上の物理シャード (同じタイプのドキュメントのコレクションのインデックス付け) を指す論理名前空間。

_type:ES7 バージョンのデフォルトは _doc です。

_id:ドキュメントタグはシステムによって自動的に生成され、一意です。

断片化構造の実装:

分散システムでは、単一のマシンに巨大なデータを保存することはできません。したがって、データをいくつかの小さな部分に分割して各マシンに割り当てる必要があります。次に、路由策略特定の方法で特定のデータ ブロックの場所を見つけ、水平拡張機能を向上させるためにデータをシャーディングすることに加えて、分散ストレージはデータを複数のコピーにコピーして異なるマシンに配置します。データ コピーでは、読み取り操作も同時に実行できます。
同時更新の問題に対処するために、ES はデータ コピーをマスターとスレーブの 2 つの部分、つまり、信頼できるデータとしてプライマリ データ主分片(プライマリ シャード) と副分片(レプリカ シャード) に分割します。が最初に書き込まれ、成功後にセカンダリ シャードが書き込まれます。リカバリ フェーズはプライマリ シャードに基づいています。

シャードは、基礎となる基本的な読み取り/書き込みユニットです。シャードの目的は、巨大なインデックスを分割して、複数のマシンで読み取りと書き込みを並行して実行できるようにすることです読み取りおよび書き込みリクエストは最終的にシャードに分類され、シャードは読み取りおよび書き込み作業を独立して実行できます。ES はシャーディングを使用してクラスター全体にデータを分散します。シャードはデータのコンテナであり、ドキュメントはシャード内に保存され、シャードを越えて保存されることはありませんシャードはクラスター内の各ノードに分散されますクラスターのサイズが拡大または縮小すると、ES は各ノード間でフラグメントを自動的に移行するため、データはクラスター内で均等に分散されます。

ES インデックスには多くのシャードが含まれており、シャードは Lucene インデックスであり、それ自体がインデックス作成と検索機能を独立して実行できる完全な検索エンジンです。Lucene インデックスは多くの分段コンポーネントで構成されており、各セグメントは転置インデックスですES を「更新」するたびに、複数のドキュメントのデータを含む新しいセグメントが生成されます。

各セグメント内では、ドキュメントのさまざまなフィールドに個別にインデックスが付けられます各フィールドの値は複数の単語 (用語) で構成され、用語はトークナイザーと言語によって処理された後の元のコンテンツの最終結果です (たとえば、句読点の削除と単語のルートへの変換)。

断片化とデータの関係:

インデックスを作成するときは、シャードの数を決定する必要があります。現在 (バージョン 5x ~ 6x 以降)、ES は特定の条件下でインデックスのプライマリ シャードを分割 (Splt) または縮小 (Shrink) します。ただし、最初からプライマリ シャードの数をできるだけ多く計画する必要があります。まずハードウェアの状況に応じて 1 つのシャードの容量を決定し、次にビジネス シナリオに応じてデータ量と増加を見積もり、分割します。単一シャードの容量によって異なります。

シャードの数が十分でない場合は、新しいインデックスの作成を検討できます。50 個のシャードでインデックスを検索することは、それぞれ 1 シャードで 50 個のインデックスを検索することと完全に同等です。または、分割 AP を使用してインデックスを分割します (バージョン 6 開始サポート) )

実際には、シャードが巨大になるまで単一のインデックスにデータを書き込み続けるべきではありません。データが古くなると、巨大なインデックスを削除するのは困難になります。ID でドキュメントを削除しても、すぐにスペースが解放されるわけではありません。削除されたドキュメントは、Lucene セグメントがマージされた場合にのみディスクから削除されます。セグメントのマージを手動でトリガーした場合でも、高い IO プレッシャーが発生し、セグメント サイズが大きい (セグメント サイズが使用可能なディスク領域の半分を超えている) ため、マージ プロセス中にディスク領域が不足する可能性があります。したがって、新しいインデックスを定期的に作成することをお勧めします。たとえば、1 日に 1 つ作成します。インデックス Web サイトがある場合は、website20180319 という名前を付けることができます。次に、これらのインデックスを関連付けるために、web サイトという名前のインデックス エイリアスを作成します。このように、ビジネス側では、読み取り時に使用される名前は変更されず、データを削除する必要がある場合は、インデックス全体を直接削除できます。

インデックス エイリアスは、1 つ以上のインデックスを指すことができる点を除けば、ショートカットまたはソフト リンクに似ています。インデックスのグループ化やインデックス間のシームレスな切り替えを実現するために使用できます。

プライマリ シャードの数を決定し、1 つのインデックスのデータ量が大きくなりすぎないようにしましたが、新しいインデックスを定期的に作成することによって引き起こされる新たな問題は、クラスター内のシャードの総数が大きくなり、クラスターによって管理されるシャードの総数 増加すると、プレッシャーも大きくなります。新しいインデックスが毎日生成されるシナリオでは、特定の日に生成されるデータの量は少ない可能性があり、実際にはそれほど多くのシャードは必要なく、1 つでも十分です。このとき、Shrink APL を使用すると、プライマリ フラグメントの数を減らし、クラスターの負荷を軽減できます。

転置インデックスとは:

元のデータは次のとおりです。

ID 名前 セックス
1 ケイト 23 女性
2 ジョン 23
3 末野 21

ID は Elasticsearch によって構築されたドキュメント ID であり、Elasticsearch によって構築されたインデックスは次のようになります。

名前:
学期 投稿一覧
ケイト 1
ジョン 2
末野 3
年:
学期 投稿一覧
23 [1、2]
21 1
性別:
学期 投稿リスト
ファマーレ 1
[2、3]

Elasticsearch は、 Kate, John, 23, Female という名前のそれぞれに対してField逆インデックスを作成しましたterm。[1,2] はPosting Listです。投稿リストは int 配列で、特定の用語に一致するすべてのドキュメント ID を格納します。

逆ソートとは、文書の情報に従って、すべての適格な文書コレクションを逆方向に取得できることです。たとえば、Male情報を検索すると、ID が 2 と 3 の 2 人の情報が取得されます。

インデックスを動的に更新します。

ドキュメントのインデックスを作成し、転置インデックスのデータ構造を使用して各フィールドを検索し、キーワードを通じてドキュメントのコンテンツを取得できるようにします。

反転インデックスがファイルに書き込まれると、そのインデックスは不変性を持ちます。不変性には、ファイルへのアクセスにロックが必要ないこと、インデックスの読み取り時にファイル システムによってインデックスをキャッシュできることなど、多くの利点があります。

では、新しく追加されたドキュメントを検索可能にするためにインデックスはどのように更新されるのでしょうか?

新しく追加されたコンテンツは、まずメモリにキャッシュされます。特定の条件が満たされると、更新操作がトリガーされます。更新操作により、キャッシュされたデータがファイル システムに書き込まれ、新しい逆ソート インデックス (新しい Lucene セグメント) が生成されます。今回は、ファイルシステムキャッシュ内のデータを取得できます。クエリを実行する場合、各転置インデックスが順番にクエリされ、結果はクエリ後にマージされます。つまり、適格なすべての転置インデックスが取得され、その後、取得結果がマージされます。

  • キャッシュ内のデータはセグメントに格納されないため、取得できません。新しいセグメントが生成される限り、ディスクにまだ書き込まれていなくても、そのセグメントを取得できます。
  • セグメントは不変であるため、更新や削除などの操作では、実際にはデータに削除済みのマークが付けられ、別の場所に記録されます。この方法はマーク削除と呼ばれます。したがって、一部のデータを削除してもディスク領域は解放されません。
ほぼリアルタイムの検索:

書き込み操作では、通常、データが一度メモリにバッファリングされてからハードディスクに書き込まれ、毎回ハードディスクに書き込まれるデータのまとまりを 1 と呼びます分段通常の状況では、オペレーティング システムの書き込みインターフェイスによってディスクに書き込まれたデータが最初に系统缓存(メモリに) 到着し、書き込み関数が正常に戻ったときに、データがディスクにフラッシュされないことがあります。fash を手動で呼び出すか、オペレーティング システムが特定の戦略に従ってシステム キャッシュをディスクにフラッシュします。書き込み関数が正常に戻った時点から、データがディスクにフラッシュされたかどうかに関係なく、データはすでに読み取り可能になっています。
ES はキャッシュ内のデータを毎秒更新します。この機能により、ほぼリアルタイムの検索が可能になります。ES はデータをメモリにバッファリングし、まずファイル システム キャッシュに書き込み、新しいセグメントを生成します。書き込み操作が完了すると、セグメント ベースの逆インデックスが取得可能になります。次に、フラッシュ操作を実行して、後でディスクに書き込みます。

システムは書き込み前にデータのセクションをバッファリングし、新しいセクションはすぐにはディスクにフラッシュされないため、これら 2 つのプロセス中に予期せぬ状況 (ホストの電源障害など) が発生した場合、データが失われるリスクがあります。一般的な方法はトランザクション ログを記録することです。ES が操作されるたびに、トランザクション ログが記録されます。ES が開始されると、最後のコミット後に発生したトランスログ内のすべての変更操作が再生されます。たとえば、HBase には独自のトランザクション ログがあります。

フラグメントのマージ:

ES では、書き込みバッファが 1 秒に 1 回クリアされ、データがファイルに書き込まれます。このプロセスはリフレッシュと呼ばれ、リフレッシュのたびに新しい Lucene セグメントが作成されます。ただし、セグメントが多すぎると問題が大きくなり、各セグメントがファイル ハンドルとメモリを消費します。

各検索リクエストでは、各セグメントを順番にチェックして結果を結合する必要があるため、セグメントが多いほど検索は遅くなります。したがって、これらの小さなセグメントを大きなセグメントにマージするには、特定の戦略を使用する必要があり、一般的な解決策は、マージ対象に同じサイズのセグメントを選択することです。マージ プロセス中、削除マークが付けられたデータは新しいセグメントに書き込まれません。マージ プロセスが終了すると、古いセグメント データが削除され、削除マークが付けられたデータはディスクから削除されます。
HBase や Cassandra などのシステムにも同様のセグメント化メカニズムがあります。書き込みプロセス中、データのバッチは最初にメモリにバッファリングされ、これらのデータは時々セグメントとしてファイルに書き込まれます。セグメントは不変であり、その後、いくつかの戦略を通じてセグメントがマージされます。セグメントのマージ中、新しいセグメントを作成するには一定量のディスク領域が必要であり、システムに十分な空き領域が残っていることを確認する必要があります。

セグメントのマージ中の Cassandra システムの問題は、データがテーブルに継続的に書き込まれる場合、セグメント ファイルのサイズに上限がない場合、巨大なセグメントがディスク領域の半分に達すると、残りの領域が十分ではなくなることです。新しいセグメントの結合プロセス。セグメントファイルの上限が設定されてマージされなくなった場合、テーブル内の一部のデータは物理的に削除できなくなります。ESにも同じ問題があります。

3. クラスター (ノード) の内部原理:
1) マスターノード

マスター ノードは、インデックスの作成、インデックスの削除、およびクラスター内のノードのステータスの追跡を担当します。
node.master:true (デフォルト) を設定すると、ノードはマスターとして選出される資格が得られます。マスター ノードはグローバルに一意であり、マスターになる資格のあるノードから選出されます。
マスター ノードはデータ ノードとしても使用できますが、作業はできるだけ少なくする必要があるため、運用環境ではマスター ノードとデータ ノードを分離し、独立したマスター ノード構成を作成する必要があります。ノードデータ: false

データ損失を防ぐために、各マスター ノードは適格なマスター ノードの数を知っている必要があります。デフォルトでは 1 です。ネットワークが分割されている場合に複数のマスターを避けるため、構成は Discovery.zen.minimum_master_nodes です。原則として、最小値はあるべきです(master_eligible_nodes/2)+1

2) データノード

データの保存、CRUD、検索、集計などのデータ関連操作の実行を担当します。データ ノードには、CPU、メモリ、および IO に関するより高い要件があります。

通常の状況では、データの読み取りおよび書き込みプロセスはデータ ノードとのみ対話し、マスター ノードは処理しません (異常な状況を除く)。
(デフォルト) を設定してnode.data:true、ノードをデータ ノードにします。

3) 前処理ノード

前処理操作により、ドキュメントのインデックスを作成する前、つまりデータを書き込む前に、一連の事前定義されたプロセッサー (プロセッサー) とパイプライン (パイプライン) を介してデータの変換と強化が可能になります。
プロセッサとパイプラインは、buk リクエストとインデックス リクエストをインターセプトし、関連する操作を適用した後、ドキュメントをインデックス API またはバルク API に返します。

デフォルトでは、取り込みはすべてのノードで有効になっています。ノードで取り込みを無効にしたい場合は、構成node.ingest:falseを追加できます。

次の構成で前処理専用ノードを作成することもできます。

node.master:false 
node data:false 
node.ingest:true
4) コーディネーターノード

クライアント要求はクラスター内の任意のノードに送信でき、各ノードはドキュメントがどこにあるかを認識して、これらの要求を転送し、データを収集してクライアントに返します。クライアント要求を処理するノードは調整ノードと呼ばれます。
コーディネーターノードは、データを保持するデータ ノードにリクエストを転送します。各データ ノードはリクエストをローカルで実行し、結果をコーディネータ ノードに返しますコーディネーター ノードはデータを収集した後、各データ ノードからの結果を単一のグローバル結果に結合します。結果を収集して並べ替えるプロセスには、大量の CPU リソースとメモリ リソースが必要になる場合があります。
以下の構成で調整専用ノードを作成します

node.master:false 
node data:false 
node.ingest:false
5) ホードノード

トライブ機能を使用すると、トライブ ノードが複数のクラスターにわたるフェデレーション クライアントとして機能できるようになります。
ES5.0 より前には、クライアント ノード (ノード クライアント) ロールもあり、クライアント ノードには次の属性がありました。

node.master:false 
node data:false 

これはマスター ノードやデータ ノードとして機能せず、リクエストのルーティングにのみ使用され、本質的にはインテリジェントなロード バランサーです (ロード バランサーの定義によると、インテリジェントと非インテリジェントの違いは、ロード バランサーがどこにあるかを知っているかどうかです)アクセスされたコンテンツが存在します。ノード)、バージョン 5.0 以降、このロールはコーディネーター ノードに置き換えられます。

4. クラスターの健全性ステータス (検出):

データ整合性の観点から、クラスターの健全性ステータスは次の 3 つのタイプに分類されます。

  • 緑色、すべてのプライマリ シャードとセカンダリ シャードが稼働中です。
  • 黄色、すべてのプライマリ シャードは稼働していますが、すべてのセカンダリ シャードが稼働しているわけではありません。これは、単一障害点のリスクがあることを意味します。
  • 赤、プライマリ シャードが正しく機能していません。

各インデックスにも上記 3 つの状態があり、サブシャードが失われ、そのシャードが属するインデックスとクラスター全体が黄色になり、その他のインデックスは緑色のままになります。

5. Elasticsearch で一般的に使用されるトークナイザー:

標準トークナイザー (デフォルトのトークナイザー): 英語を処理する強力な機能があり、語彙単位を小文字に変換し、ストップワードと句読点を削除し、英語以外の単語を単一の単語に分割します。

ホワイトスペース (スペーストークナイザー): 英語の場合、他の処理を行わずにスペースのみを削除します。英語以外はサポートされません。

シンプル: 英語の場合、テキスト情報がアルファベット以外の文字で分割され、語彙単位が小文字に統一され、数値タイプの文字が削除されます。

Stop: StopAnalyzer の機能は SimpleAnalyzer を上回っており、SimpleAnalyzer をベースに、英語の一般的な単語 (the、a など) の削除を追加し、設定が必要な一般的な単語も追加できます。サポートされました。

キーワード: KeywordAnalyzer は、テキストを分割せずに、入力全体を単一の語彙単位として扱います。通常、郵便番号、電話番号、および完全一致が必要なその他のフィールドで使用されます。

パターン (正規一致): クエリ テキストは正規表現として自動的に処理され、一連の用語キーワードが生成され、Elasticsearch にクエリが実行されます。

言語: アラビア語、アルメニア語、バスク語、ブラジル語、ブルガリア語、カタロニア語、cjk、チェコ語、デンマーク語、オランダ語、英語、フィンランド語、フランス語、ガリシア語、ドイツ語、ギリシャ語、ヒンディー語、ハンガリー語、インドネシア語などの特殊言語テキストを解析するためのアナライザー コレクション。アイルランド語、イタリア語、ラトビア語、リトアニア語、ノルウェー語、ペルシア語、ポルトガル語、ルーマニア語、ロシア語、ソラニ語、スペイン語、スウェーデン語、トルコ語、タイ語、ただし中国語は含まれません。

Snowball (snowball トークナイザー): Snowball フィルターは、Lucene によって公式に推奨されていない標準に基づいて追加されます。

カスタム (カスタム ワード ブレーカー): 階層をカスタマイズできます。フィルター リストのワード ブレーカーは次のとおりです。

index :
    analysis :
        analyzer :
            myAnalyzer2 :
                type : custom
                tokenizer : myTokenizer1
                filter : [myTokenFilter1, myTokenFilter2]
                char_filter : [my_html]
                position_increment_gap: 256
        tokenizer :
            myTokenizer1 :
                type : standard
                max_token_length : 900
        filter :
            myTokenFilter1 :
                type : stop
                stopwords : [stop1, stop2, stop3, stop4]
            myTokenFilter2 :
                type : length
                min : 0
                max : 2000
        char_filter :
              my_html :
                type : html_strip
                escaped_tags : [xxx, yyy]
                read_ahead : 1024

IKAnalyzer (IK トークナイザー): KAnalyzer は、Java 言語に基づいて開発されたオープンソースの軽量の中国語単語分割ツールキットです。

独自の「順方向反復細粒セグメンテーションアルゴリズム」を採用し、細粒と最大ワード長の2つのセグメンテーションモードをサポートし、83万ワード/秒(1600KB/S)の高速処理能力を備えています。

マルチサブプロセッサ分析モードを採用し、サポート: 英語の文字、数字、中国語の語彙などの単語分割処理、韓国語と日本語の文字と互換性があり、ユーザー定義のシソーラスをサポート、IK 単語分割デバイスのダウンロード アドレス: https://github .com/medcl/elasticsearch-analysis-ik

次の 2 つのトークナイザーが付属しています。

  • ik_max_word: テキストを最も細かい粒度に分割し、できるだけ多くの単語を分割します。
  • ik_smart: 最も粗い分割を実行すると、分割された単語が再び他の単語によって占有されることはなくなります。

Pinyin (ピンイン ワード ブレーカー): ユーザーによるピンイン入力を通じて Elasticsearch の中国語と一致します。ピンイン ワード ブレーカーのダウンロード アドレス: https://github.com/medcl/elasticsearch-analysis-pinyin

注: ワード ブレーカーを追加または変更する前にインデックスを閉じる必要があります。追加または変更が完了したら、検索やその他の操作のためにインデックスを開いてください。

おすすめ

転載: blog.csdn.net/weixin_43322048/article/details/113809037