一、基本概念#
-
NRT:
Near Realtime、近リアルタイム、2 つの側面を持つ。一つはデータを書き込んでからそのデータが検索可能になるまでの非常に短い遅延(約 1 秒程度)があること、もう一つは Elasticsearch に基づく検索と分析操作の時間が秒単位に達すること。 -
Cluster
クラスター、外部にインデックスと検索のサービスを提供し、1 つ以上のノードを含む。各ノードがどのクラスターに属するかはクラスター名によって決まる(デフォルト名は elasticsearch)。 -
Node
単独の Elasticsearch サーバーインスタンスは 1 つのノードと呼ばれ、ノードはクラスターの一部である。各ノードには独自の名前があり、デフォルトでは起動時に UUID を取得して名前とすることができ、自分で設定することも可能。1 つのノードは 1 つの Elasticsearch クラスターにのみ参加できる。 -
primary shard
プライマリシャード、データの保存単位、シャードを増やすことで横方向にスケールアウトでき、インデックス作成時に指定され、作成後は変更できない。 -
replica shard
レプリカシャード、シャードのデータコピーとして機能し、データの損失を防ぎ高可用性を保証し、同時にシャードの検索リクエストを分担し、クラスター全体のスループットとパフォーマンスを向上させる。 -
Index
インデックス、同じ構造のドキュメントの集合、データベースのデータベースインスタンスに相当する(Es 6.0 でタイプが廃止された後は実質的に単一のデータテーブルとなった)。 -
type
タイプ、Es 6.0 以降廃止、参考リンク: Removal of mapping types -
Document
ドキュメント、Elasticsearch の最小データ保存単位、JSON データ形式、リレーショナルデータベースのテーブルレコード(1 行のデータ)に類似しており、構造の定義は多様で、同じインデックス内のドキュメントはできるだけ同じ構造であることが望ましい。
Lucene 検索#
Lucene 概念#
検索の基本プロセス:クエリ分析 => 分詞 => キーワード検索 => 検索順位付け
倒排インデックス#
従来の検索は記事を通じて、キーワードの位置を 1 つずつ探し出すものであった。しかし、倒排インデックスは分詞戦略を通じて、単語と記事のマッピング関係表を形成し、O (1) の時間でキーワードを通じて記事リストを見つけることができる。簡単に言えば、内容に基づいてドキュメントを探すものであり、MySQL などの正排インデックスはID に基づいてドキュメントを探すものである。
底層の実装は FST(有限状態遷移器)データ構造に基づいている。Lucene は 4 + バージョン以降、大量に FST データ構造を使用している。FST には 2 つの利点がある:
-
スペースの占有が少ない。辞書内の単語の接頭辞と接尾辞の再利用を通じて、ストレージスペースを圧縮する。
-
クエリ速度が速い。O (len (str)) のクエリ時間計算量。
参考リンク🔗:
二、Elasticsearch 使用#
増删改查#
- Get API
- Delete API
- Update API
- Bulk API
検索#
- Search API
- Aggregrations
- Query DSL
- Elasticsearch SQL
Analyzer 分詞#
Standard Analyzer
:デフォルトの分詞器、単語に基づいて分割し、大文字を小文字に変換する。Simple Analyzer
:非アルファベットに基づいて分割(記号がフィルタリングされる)し、大文字を小文字に変換する。Stop Analyzer
:ストップワード(the、is)に基づいて分割し、大文字を小文字に変換する。Whitespace Analyzer
:空白に基づいて分割し、大文字を小文字に変換しない。IK
:中国語分詞器、プラグインのインストールが必要。ICU
:国際化分詞器、プラグインのインストールが必要。jieba
分詞:現在人気のある中国語分詞器。
インデックス管理#
alias 別名#
-
複数のインデックスをグループ化する。
月ごとにインデックスを作成する際、最初に日ごとにインデックスを作成し、インデックステンプレート(
indices templates
)を使用してログデータを日ごとに自動的に作成し、その後月次のインデックスエイリアスを使用して日ごとのインデックスを分類することができる。 -
インデックスを柔軟に変更し、インデックスを変更する際にコードを変更する必要がなく、ゼロダウンタイムでインデックスデータを移行する。
例えば、インデックスを変更する必要がある場合(シャードの変更、マッピングの変更、リネームなど)、新しく作成したインデックスを対応するエイリアスにバインドするだけで、データ移行が完了した後に旧インデックスとエイリアスのバインド関係を削除することができる。
ゼロダウンタイム移行は公式文書を参考に: Changing Mapping with Zero Downtime
-
同じインデックスの異なる「ビュー」を作成するために使用できる。
マルチテナントのシナリオに適しており、異なるユーザーが特定のインデックス内の異なるデータを見る必要がある場合、
filtered alias
(フィルタリングエイリアス)を作成することでフィルタリングを行うことができる。
-
複数の物理インデックスがあり、エイリアスを通じて書き込む必要があるシナリオ。
複数の物理インデックスがあり、エイリアスを通じて書き込む必要がある場合、
write index
を指定することで、複数のインデックスを指すエイリアスのすべてのインデックスと更新リクエストが 1 つのインデックス、すなわち書き込みインデックスとして解釈される。各エイリアスは 1 回の書き込みインデックスとして 1 つのインデックスを割り当てることができる。書き込みインデックスが指定されておらず、エイリアスが複数のインデックスを参照している場合、書き込みは許可されない。
例操作:
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
"actions" : [
{ "remove" : { "index" : "test1", "alias" : "alias1" } },
{ "add" : { "index" : "test2", "alias" : "alias1" } }
]
}
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
"actions" : [
{
"add" : {
"index" : "test1",
"alias" : "alias2",
"filter" : { "term" : { "user" : "kimchy" } }
}
}
]
}
参考リンク : Index Aliases
rollover API#
日付に基づいてインデックスをロールオーバーして作成する。
参考リンク : Rollover Index
インデックスマッピング#
- Mapping 設定
Index Template
Dynamic Template
: Elasticsearch が認識するデータタイプに基づき、フィールド名と組み合わせてフィールドタイプを動的に設定する。
参考リンク:
routing ルーティング#
ドキュメントをインデックスする際、ドキュメントはプライマリシャードに保存される。Elasticsearch はどのドキュメントがどのシャードに保存されるべきかをどのように知るのか?ドキュメントを作成する際、どのようにしてこのドキュメントがシャード1
に保存されるべきか、またはシャード2
に保存されるべきかを決定するのか?
実際、このプロセスは以下の公式に基づいて決定される:
shard = hash(routing) % number_of_primary_shards
routing
は可変値で、デフォルトではドキュメントの_id
であり、カスタム値に設定することもできる。routing
はハッシュ関数を通じて数字を生成し、その数字をnumber_of_primary_shards
(プライマリシャードの数)で割った余りが、私たちが探しているドキュメントの所在シャードの位置である。
これが、インデックスを作成する際にプライマリシャードの数を確定し、その数を決して変更しない理由である。数が変わると、以前のすべてのルーティング値が無効になり、ドキュメントも再び見つからなくなるからである。(新しいバージョンでは、Es は一定の条件制限の下で、特定のインデックスのプライマリシャードをSplit分割またはShrink縮小することをサポートしているが、n 倍に分割するか、プライマリシャード数 /n 個に縮小することしかできず、8 から 9 や 9 から 8 のような変更はできない)。
三、クラスターアーキテクチャ#
クラスター役割#
- Master Node 主ノード:全体で唯一、クラスター選挙。クラスター層の関連操作を担当し、クラスターの変更を管理する。主ノードはデータノードとしても機能できるが、推奨されない。
- Data Node データノード:データを保存し、データ関連の操作を実行する。一般的にデータの読み書きプロセスはデータノードとのみ相互作用する。
- Ingest Node前処理ノード: Es 5.0 バージョンで導入された概念。前処理操作は、ドキュメントをインデックスする前、すなわちデータが書き込まれる前に
processors
プロセッサとpipeline
パイプラインを定義してデータを変換することを可能にする。参考リンク:Ingest Node - Coordinating node 調整ノード:調整ノードはクライアントリクエストをデータを保存する Data Node に転送し、各データノードはローカルでリクエストを実行し、結果を調整ノードに返す。調整ノードはこれらのデータ結果を収集し、単一の全体結果に統合する。
- Tribe Node部族ノード、廃止され、Cross-cluster searchに置き換えられた。
クラスター健康状態#
- Green: すべてのプライマリシャードとレプリカシャードが正常に動作している。
- Yellow: プライマリシャードは正常だが、すべてのレプリカシャードが正常に動作しているわけではなく、単一障害点のリスクが存在することを意味する。
- Red: プライマリシャードの一部が正常に動作していない。
各インデックスにも上記の 3 つの状態があり、特定のレプリカシャードが正常でない場合は Yellow 状態となる。
curl -X GET "localhost:9200/_cluster/health?pretty"
を使用してクラスターの状態を確認できる。具体的には:Cluster health APIを参照。
クラスター拡張#
クラスターを拡張し、ノードを追加する際、シャードはクラスターの各ノードに均等に分配され、インデックスと検索プロセスの負荷を均等に分散させる。これらはすべてシステムによって自動的に完了する。
参考: 拡張設計
主要内部モジュール#
####Cluster
Cluster モジュールは主ノードがクラスター管理を実行するためのラッピング実装であり、クラスターの状態を管理し、クラスター層の設定情報を維持する。主な機能は以下の通り:
- クラスターの状態を管理し、新しく生成されたクラスター状態をすべてのノードに発行する。
- allocation モジュールを呼び出してシャードの割り当てを実行し、どのシャードがどのノードに割り当てられるべきかを決定する。
- クラスターの各ノード間で直接シャードを移動し、データのバランスを保つ。
allocation#
シャードの割り当てに関連する機能と戦略をラッピングしており、プライマリシャードの割り当てとレプリカシャードの割り当てを含む。このモジュールは主ノードによって呼び出される。新しいインデックスの作成やクラスターの完全な再起動にはシャードの割り当てプロセスが必要である。
Discovery 発見モジュール#
クラスター内のノードを発見し、主ノードを選挙する役割を担う。ノードがクラスターに参加または退出する際、主ノードは適切な行動を取る。ある意味で、発見モジュールは ZooKeeper のような役割を果たし、主ノードを選挙し、クラスターのトポロジーを管理する。
gateway#
主ノードからのクラスター状態(clusterstate)データの永続的な保存を担当し、クラスターが完全に再起動する際にそれらを復元する。
Indices インデックスモジュール#
グローバルレベルのインデックス設定を管理し、インデックスレベルの設定(インデックス設定はグローバルレベルと各インデックスレベルに分かれる)を含まない。また、インデックスデータの復元機能をラッピングしている。クラスター起動段階で必要なプライマリシャードの復元とレプリカシャードの復元はこのモジュールで実装されている。
HTTP#
HTTP モジュールは JSON over HTTP の方式で ES の API にアクセスすることを許可する。HTTP モジュールは本質的に完全に非同期であり、応答を待つためにスレッドをブロックすることはない。非同期通信を使用することで HTTP の利点は C10k 問題を解決することである(10k レベルの同時接続)。特定のシナリオでは、HTTP keepalive を使用してパフォーマンスを向上させることを検討できる。注意:クライアントで HTTP チャンクを使用しないこと。
Transport 伝送モジュール#
クラスター内のノード間の内部通信に使用される。1 つのノードから別のノードへの各リクエストは伝送モジュールを使用する。HTTP モジュールと同様に、伝送モジュールも本質的に完全に非同期である。伝送モジュールは TCP 通信を使用し、各ノードは他のノードといくつかの TCP 長接続を維持する。内部ノード間のすべての通信はこのモジュールによって担われる。
Engine#
Engine モジュールは Lucene の操作と translog の呼び出しをラッピングしており、シャードの読み書き操作の最終的な提供者である。
ES は Guice フレームワークを使用してモジュール化管理を行っている。Guice は Google が開発した軽量な依存性注入フレームワークである。ソフトウェア設計では、具象ではなく抽象に依存することがよく言われるが、IoC はこの理念の実現方法であり、内部でオブジェクトの作成と管理を実装している。