書評『Elasticsearch実践ガイド』
ElasticsearchはApache Luceneをベースにしたオープンソースの検索エンジンです。Elasticsearchを使えば大量データの中からキーワードを全文検索したり、ログの解析を行うといったシステムが比較的簡単に構築できます。この書籍はそのElasticsearchの使い方や運用などについて書かれています。
内容
第1章 Elasticsearchとは
第1章ではElasticsearchの概要についての説明です。
Elasticsearchが得意とするのは、複数の文書の中から特定の文字列をキーに目的の文書を探す、全文検索です。ApacheのLuceneというソフトをベースに作られています。もともとは開発者Shay Banonさんが妻の料理レシピ情報を検索するために作ったのが始まりだそうです。
全文検索の方法としては大きく分けると、以下の2つに分かれます。
- 逐次検索 … ファイルの内容を順次走査しながら目的の文字列を探す
- 索引検索 … 文書を高速に検索するために、事前に検索用の索引を作っておく
Elasticsearchは後者の索引検索を使用しています。そしてその索引には転置インデックスを使っているそうです。これは文書内に含まれる各単語と、その単語が含まれる文書の組み合わせをインデックスとして構成する方式です。
Elasticsearchは結構バージョンが変わるようですね。過去のバージョンの推移についても書かれています。ちなみにこの書籍が書かれた時点では6.2とのこと。
著者はElasticsearchの特徴として、以下の4点を挙げています。
- 分散配置による高速化と高可用性の現実
- シンプルなREST APIによるアクセス
- JSONフォーマットに対応した柔軟性の高いドキュメント志向データベース
- ログ収集・可視化などの多様な関連ソフトウェアとの連携
Elasticsearchの実際の導入事例として、日本経済新聞社の記事の全文検索、NAVER社のアプリケーションログの収集・解析について簡単に紹介されています。
本家の方にも事例のページがあるそうです。
第2章 Elasticsearchの基礎
この章からは実際にElasticsearchをインストールする作業になります。が、その前にElasticsearchの用語と概念の説明です。
用語と概念
Elasticsearchでは格納する1つの文章をドキュメントと呼びます。リレーショナルデータベースで言うところのレコードです。またドキュメントを格納する場所をインデックスと呼びます。こちらはテーブルですね。ちなみにこのインデックスはシャードと呼ばれる単位に分割されて、各ノードに分散されて保存されるそうです。
さらにフィールド、ドキュメントタイプ、マッピングについての説明が記載されています。フィールドはリレーショナルデータベースと同じフィールドですね。ドキュメントタイプとマッピング定義を合わせてテーブル定義、といった感じでしょうか。
また物理的な概念としてノード、クラスタ、シャード、レプリカについて書かれています。Elasticsearchではインデックスのデータを分割して複数のノードで分散することで、検索性能をスケールさせることができるそうです。その際に分割した各部分のことをシャードと呼びます。このシャードは各ノードに保存され、さらに各ノードはクラスタを構成します。
こういったElasticsearchでよく使われる用語の説明がここでは書かれています。
システム構成
クラスタを構成する各ノードの説明です。ノードの種別としては
- Master (Master-eligible)
- Data
- Ingest
- Coordination
が、あるそうです。1台に複数の属性を持たせることも可能とのこと。
各ノードがクラスタの中でどういう役割を持ち、どうやってMasterノードが選定されるのか、どのようにノードはクラスタに参加するのか、などについて説明されています。また用語の説明で出てきたシャードとレプリカについて、さらに詳しい説明が書かれています。シャード数やレプリカ数の決め方についても記載されていて、非常に参考になりました。
REST APIによる操作
ElasticsearchではREST APIを使って操作を行います。ここではHTTPそのものの説明や、エンドポイントについての説明、APIをアクセスするために使用するcurlコマンドの説明などが記載されています。
Elasticsearchの導入方法
そしていよいよインストールです。本書ではCentOS7とUnuntu16.04にOpenJDKとElasticsearchをインストールする方法が書かれています。Dockerについても簡単ではありますが説明されていました。Windows版についての説明はありませんがzipを用いたインストール手順があるので、そちらが参考になると思います。
インストールが終わったら、REST APIへアクセスして確認です。
curl -XGET http://localhost:9200/
最後は設定についてです。
- elasticsearch.yml
- jvm.options
- log4j2.properties
上記3つの設定ファイルについて、代表的な設定項目が説明されています。
第3章 ドキュメント/インデックス/クエリの基本操作
第3章ではREST APIを使ってCRUD動作を行います。この書籍ではcurlコマンドを使ってAPIにアクセスします。
ドキュメントの基本操作
ドキュメントをインデックスに登録するには、PUT/POSTを使います。PUTの場合はユニークなキーとなるドキュメントIDを自分で指定できます。POSTの場合はドキュメントIDは自動生成されます。
登録したドキュメントを読むためにはGETメソッドを使います。ドキュメントIDを指定して取得する場合は、URLにドキュメントIDを指定することで取ってくることができます。
curl -XGET 'http://localhost:9200/my_index/my_type/1'
ドキュメントの更新はPUTメソッドを使います。更新にはドキュメントIDを指定します。書籍ではドキュメント全体を更新する方法と、一部を 更新する方法が説明されていますが、内部的にはどちらも既存のドキュメントを一度削除して、新しいバージョンのドキュメントを再インデックスする、という動作になるそうです。
ドキュメントの削除はDELETEメソッドを使います。ドキュメントIDを指定して削除します。
インデックスとドキュメントタイプの管理
Elasticsearchでは事前にインデックスやドキュメントタイプを作成していなくても、型などを自動で推測してくれるため、エラーにならずに登録できます。
しかし
- デフォルト値とは違うレプリカ数やシャード数を指定したい場合
- 型を自動推測してほしくない場合
と、いった場合には、事前にインデックスやマッピング定義を作成しておくことになります。ここでは、これらの操作をREST APIを使用して行う方法が記載されています。
インデックスの作成時にはレプリカ数やシャード数を指定することができます。またインデックスの設定を後から更新することもできますが、プライマリシャード数の変更はできないとのことです。DELETEメソッドでインデックスの削除もできます。
また、ドキュメントタイプを作成し、各フィールドの型などを定義するマッピング定義も事前に作成できます。リレーショナルデータベースでいうところのテーブル定義を作成するということですね。こちらもREST APIでBODY部にJSONを記述することで、作成します。あとからフィールドを追加することも可能だそうです。
さらにインデックステンプレートというものも使えます。インデックスの定義をテンプレートとして保存しておきます。新しく作成されるインデックス名が、このテンプレートで指定されているパターン名にマッチする場合、この定義が適用されるというものです。例えばインデックスのパターンとして”accesslog-*”と指定しておくと、accesslog-で始まるインデックスを作成すると、このテンプレートが適用されます。
さまざまなクエリ
そして検索条件を指定してドキュメントを検索するクエリについての説明です。検索をするためには、要の機能ですね。リレーショナルデータベースでいうところのWHEREになります。
検索にはURIサーチと言われる簡易的な検索と、クエリDSLと呼ばれるものがあります。
URIサーチでは
curl -XGET 'http://localhost:9200/<インデックス名>/<タイプ名>/_search?q=<フィールド名>:<検索キーワード>'
といった形で検索できますが、簡単な検索しかできません。
クエリDSLではリクエストのBODY部に検索条件をJSONで記述します。
1 2 3 4 5 6 7 |
{ "query": {<クエリ内容>}, "from": 0, "size": 10, "sort": [<ソート>], "_source": [] } |
基本的にはこちらのクエリDSLを使って、検索を行うことになります。Elasticsearchでは以下のような予約語を使って、クエリ内容を組み立てます。
- match_all ... 全てのドキュメントを返す
- match ... キーワード検索
- match_phrase ... 語順も考慮される
- query_string ... Lucene形式での検索式
- term ... 完全一致検索
- terms ... 複数のtermを指定できる
- range ... 数値は日付などの範囲検索
- bool,must,should,must_not ... andやorなどの検索
- filter ... スコアを返さない
リレーショナルデータベースのWHEREとは全く違った形なので、新たに覚えないといけないですね...書籍では各検索クエリが説明されています。
またクエリ結果のソートとして、
- フィールド名を1つ指定
- フィールド名を複数指定
- スコアに基づいたソート
- 配列型データの算術計算結果に基づいたソート
が紹介されています。
第4章 Analyzer/Aggregation/スクリプティングによる高度なデータ分析
この章ではさらに高度な機能の説明です。具体的には全文検索に使われるAnalyzerと、データ分析のためのAggregation、データの細かい処理を行うスクリプティングについての説明です。
Analyzer
Elasticsearchでは、全文検索を行うために文章を単語の単位に分割する処理機能を、Analyzerと呼びます。
例えば”マラソンが東京で開催される”という文章があった場合、以下のように分割されます。
”マラソン”、”が”、”東京”、”で”、”開催”、”さ”、”れる”
ちなみにElasticsearch標準のAnalyzerでは日本語の形態素解析が行えないため、kuromojiプラグインをインストールする方法が書籍では紹介されています。
またコラムの中でN-gramについても簡単に説明されています。上記の文章は2文字区切りのN-gram(2-gram)なら
”マラ”、”ラソ”、”ソン”、”ンが”、”が東”、”東京”、”京で”、”で開”、”開催”、”催さ”、”され”、”れる”
になります。どちらの分割方法にもそれぞれの利点と欠点があるようです。
Analyzerは
- Char filter ... 入力されたテキストを前処理するためのフィルタ
- Tokeneizer ... テキストの分割処理
- Token filter ... 分割されたテキスト(トークン)に対する処理を行うフィルタ
という3つの組み合わせから成り、それぞれのビルトインの機能と、その設定方法が説明されています。
例えばChar filterにはHTMLのタグを除去するHTML Strip Character Filter、Tokenizerには単語分割のTokenizer、Token filterには全てを小文字にするLower case Token filterなどがあり、ほかにも代表的なものが本書では紹介されています。
Aggregation
Aggregationとは検索結果の集合に対して、分類や集計を行うことができる機能です。SQLでいうところのSUM()、AVG()といった関数やGROUP BYです。ElasticsearchではSUM()などの関数はMetrics、GROUP BYで集計されるグループをBucketsと呼ぶそうです。
また、他のAggregationの結果を用いてさらに集計するPipeline、複数のフィールドを対象に相関や共分散などの統計値を計算できるMatrixという機能もあります。
ここではMetricsやBucketsを使ったクエリの書き方などが説明されています。
また少し変わったAggregationとしてsignificant termsというものが紹介されています。これは全体的に見ると目立たないけれど、特定の範囲の中で見ると突出して目立つ、といった特徴を持つものを探してくれるそうです。
スクリプティング
ElasticsearchではPainlessと呼ばれるスクリプティング言語を使うことによって、ユーザー独自のロジックを実装することができます。スクリプティングを使うことで
- フィールドの上書き更新を行う
- 条件を満たすドキュメントの特定フィールドのみを一度に上書き更新する
- 古いインデックスに含まれるフィールドをすべて更新して新しいインデックスを再作成する
などができるようになります。例えば以下のスクリプトで特定のpriceフィールドを書き換えつつ、インデックスを再作成(reindex)することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "source": { "index": "painless_test_old" }, "dest": { "index": "painless_test_new" }, "script": { "lang": "painless", "source": "ctx._source.price += params.price_raise", "params" { "new_price": 100 } } } |
第5章 システム運用とクラスタ管理
この章では運用についての説明です。
運用監視と設定変更
以下の4つの方法を使った運用状況の確認方法が紹介されています。
- _cat APIを利用した動作確認
- クラスタAPIを利用した動作確認
- X-pack Monitoring機能を利用した動作確認
- Elasticsearchの出力するログの確認
_cat APIとクラスタAPIではREST APIを使用して動作状況を確認できます。
例えば_cat APIでは
curl -XGET 'http://localhost:9200/_cat/health?v'
クラスタAPIでは
curl -XGET 'http://localhost:9200/_cluster/health?v'
で、それぞれ状態確認ができます。
書籍では他にもいくつかの代表的なAPIや一覧が記載されています。
また、運用上有益なログファイルとして
- deprecatedログ
- スローログ
が挙げられています。
さらに、設定方法の変更として
- 静的な設定変更 ... 設定ファイルの変更
- 動的な設定変更 ... APIを使った変更
- 一時的なクラスタ設定変更
- 恒久的なクラスタ設定変更
についても記載されています。
クラスタの管理
クラスタの起動・停止・再起動、ノードの拡張・縮退について説明です。
クラスタ内では常にシャードのレプリケーションやバッファリング、ディスク遅延書き込みなどの仕組みが動作しているため、不用意にノードを停止したり、起動したりすると、リバランシングが起動してしまい不要なデータの移動が発生するそうです。
ここではそういったことを考慮した起動や停止方法について書かれています。また、ここに書かれているやり方で1ノードずつ停止・再起動するRolling Restartも可能とのこと。クラスタ全体を止めずに、各ノードをメンテナンスするには必須ですね。
さらに運用とともに変化するデータ容量に対応して、ノードを拡張したり、逆にノードを縮退する方法が説明されています。拡張するときの注意点としてはdiscovery.zen.minimum_master_nodesパラメータの値について、縮退するときの注意点としてレプリカを持たないシャードがある可能性を考慮しての「シャード割り当てフィルタリング」のやり方、などの説明があります。
スナップショットとリストア
スナップショットでは例としてNFSサーバー上にスナップショットを保存するやり方が書かれています。スナップショット用のリポジトリというものを作らないといけないそうです。
またリストアでは通常は同じ名前のインデックスにリストアしようとするそうですが、インデックス名を変更しつつリストアしたり、インデックス設定を変更しつつリストアする方法も書かれています。
インデックスの管理とメンテナンス
インデックスエイリアスを使ってサーバーを止めずにインデックスを切り替えたり、既存のインデックスの特定のドキュメントのみを他のインデックスにコピーする再インデックスの方法についての説明が書かれています。
再インデックスは一度設定すると変更できないシャード数の変更が必要なときにも使えるとのこと。他にも運用に便利な操作や機能が書かれています。
- インデックスのshrink ... シャード数の縮小
- curatorを利用したインデックスの定期メンテナンス
- refreshとflush ... Luceneのファイル構造とふるまいについての理解
といった具合に、運用に役立つ情報が満載です。
第6章 Elastic Stackインテグレーション
最後の章はElastic StackとX-Packについてです。
Elasticsearch自身も含めた、Elastic Stackと呼ばれるソフトウェア群があります。
- Elasticsearch
- Kibana
- Logstash
- Beats
脇を固めるソフトたちが、さらにElasticsearchを便利にしてくれます。
ここではそれぞれについての簡単な説明とインストール方法が説明されています。こちらは簡単な説明のみになっているので、詳しいことはネットなどで情報収集することになると思います。
感想
実践ガイドという名の通り、実際によく使うであろう機能に絞って解説されていて、非常に分かりやすかったです。本当に運用してきた人が書かれた書籍という感じです。
とにかく”実践”という言葉がぴったりくる、実用的な書籍でした。Elasticsearchを運用するなら必須の書籍だと思います。公式サイトでもドキュメントは公開されてますが、リファレンスという感じで通して勉強するには、ちょっと使いづらかったです。いつも思うのですが、しっかり学ぼうと思うとやはり書籍がいいですね。ネットでは断片的な情報になりがちなので。