Elasticsearch 入門。その4

2021.10.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Elasticsearch初学者の中村です。 入門その4では、 ElasticsearchのClusterやNode等の構成について書きます。

Elasticsearchの構成

Elasticsearchは大まかに、Cluster、Node、Shardによって構成されています。

各構成要素について書いていきます。

Cluster

1台以上のNodeで構築されたものがClusterと呼ばれ、1つのまとまりとしてリクエストを処理します。

Cluster State

Clusterの詳細情報(Cluster State)については GET _cluster/state で取得出来ます。 NodeやIndex、Shardの情報などを確認することが出来ます。

レスポンス

{
  "cluster_name" : "cluster-name",
  "cluster_uuid" : "noQw1b9qSLmsQHLoD4SH7g",
  "version" : 176,
  "state_uuid" : "ok_vLEOES4CHysjfo08eiw",
  "master_node" : "hOEz8NAfRlilRumW_tKKvQ",
  "blocks" : { },
  "nodes" : {
    "hOEz8NAfRlilRumW_tKKvQ" : {
      "name" : "96ecbee7d9be",
      "ephemeral_id" : "pGY-0KX6QMSfQb8Y_JaIbA",
      "transport_address" : "172.19.0.4:9300",
      "attributes" : {
        "ml.machine_memory" : "2084249600",
        "xpack.installed" : "true",
        "transform.node" : "true",
        "ml.max_open_jobs" : "20"
      }
    }
  },
  "metadata" : {
    "cluster_uuid" : "noQw1b9qSLmsQHLoD4SH7g",
    "cluster_uuid_committed" : true,
    ...
    }
    ...
}

Cluster Stateの情報は全てのNodeが保持しています。

Node

NodeはElasticsearchのインスタンスで、JVM上で動作する1プロセスになります。ElasticsearchではNode毎に役割(後述)を指定出来、それぞれの役割に沿った動きをします。

Elasticsearch上のNodeを確認するには GET _cat/nodes?v をリクエストします。

1行目は各項目のヘッダーで2行目から各Nodeの設定値が返ってきます。今回は1台のみ立ち上げているので1行だけです。 name には起動時に付与されたランダムな文字列が割り当てられています。自分で指定する場合には、 config/elasticsearch.ymlnode.name に好きな名前を指定します。

Nodeの役割

Nodeには役割(Role)を設定することが出来ます。(複数可能)

node.roles: [ data, master, ingest]

Elasticsearch7系で指定可能なRoleは以下になります。

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html

  • master
  • data
  • data_content
  • data_hot
  • data_warm
  • data_cold
  • data_frozen
  • ingest
  • ml
  • remote_cluster_client
  • transform

主なRoleについて説明していきます。

Master Node

Master NodeはCluster上に1台しか存在しない全体管理用のNodeです。 どのShardがどのNodeに存在するか、インデックスの生成・削除、どのNodeがClusterに属しているか等を管理しています。Master Nodeには実際に登録したデータは保持されません。

Elasticsearchでは master を指定されたMaster Node候補(Master-eligible Node)の中から投票というプロセスによりMaster Nodeを1台のみ選出します。

上図では3台のNodeに master を指定し、Master Node候補間で投票しあい、過半数を得票したNodeがMaster Nodeになります。上図ではNode2がMaster Nodeになりました。 Cluster内ではNodeを監視していて、障害によりMaster Nodeへの接続が切れてしまった場合、再度残ったNode間で投票しあってMaster Nodeを選出します。

Split Brain

Elasticsearchに限らず複数台のサーバーでClusterを構成している場合、Split Brainという問題が起こる可能性があります。

例えば5台のNodeで構成しているClusterが、ネットワーク障害により3台,2台と分断されてしまった場合。

今までの説明だと、3台のNodeで再投票してMaster Nodeを選出してClusterは稼働し始めます。分断された2台のNode側も同じ様に稼働しClusterが2つ稼働してしまいます。

このまま利用を続けた場合、片方のClusterにデータを登録してももう一方のClusterにはデータは登録されなかったりと不整合が起きてしまいます。 その後、ネットワーク障害が治って5台のNode間で通信が回復した際、Clusterはどのデータが正しいのか判定も出来ません。

それを解消するためにElasticsearch7系では、Master Node候補が <Master Node候補数>/2 + 1 以上存在していればClusterを構成する。という仕様になっています。 この条件を満たさない場合、Clusterは構成されず稼働を停止します。停止後にネットワーク障害が治れば、停止していたNodeはClusterに組み込まれます。

この仕様によりネットワーク障害で分断されてしまっても、稼働するClusterを1つにすることが出来、Split Brainを防ぐことが出来ます。

公式のブログにES6から7で方法が変わった経緯等が記載されていましたので、ご参考ください。

Data Node

Data Nodeはデータを保持し、CRUD、検索、集計などのデータ操作処理を行います。

These operations are I/O-, memory-, and CPU-intensive. It is important to monitor these resources and to add more data nodes if they are overloaded.

ドキュメント記載のように、検索や集計ではI/O、メモリ、CPUが重要になってきますので、Data Nodeを起動するインスタンスタイプは慎重に選択しましょう。検索や集計等エンドユーザーの検索体験に一番直結するNodeです。

data_content data_hot data_warm data_cold data_frozen は少し特殊なRoleです。

Elasticsearchではインデックスライフサイクル管理(ILM)機能が実装されており、上記Roleを利用することで Hot-Warm-Coldアーキテクチャーを実装することが出来ます。詳細については公式ブログをご参考ください。

ElasticsearchではNodeに複数のRoleを指定出来るので、利用頻度が低いうちはMasterとDataを同じNodeに割り当て、利用者が多くなり負荷が高くなってくれば、MasterとDataを分離するのも手です。

Ingest Node

Ingest NodeはドキュメントのIndex直前に前処理を行います。

DBのスキーマにはないが検索用のフィールドを追加したい、あるフィールドの文字数を保持したい等、事前に様々な処理を行うことが出来ます。

Coordinating Node

Coordinating Nodeはリクエストを受け取るNodeです。

リクエストを受け取ったCoordinating Nodeは、Cluster Stateを参照して各Data Nodeに検索するようリクエストを投げます。 各Nodeの検索結果を受け取った後、最終的なレスポンスの形に整形しクライアントに返すまでを担います。

Every node is implicitly a coordinating node. This means that a node that has an explicit empty list of roles via node.roles will only act as a coordinating node, which cannot be disabled.

Coordinating Nodeは基本的に全てのNodeが担います。 そのため、 node.roles に記載しなくてもCoordinating Nodeとして動きます。 もし専用で用意したい場合には、配列を空で定義すればCoordinating専用Nodeとして動かすことが可能です。

Shard

ShardはData Node内の実際にデータを保持・管理する箇所で、その実態は Apache Luceneのインスタンスです。

今まで操作してきたIndexは実は論理グループで、実際には各Shardに分散されて保持されます。

ShardにはPrimary, Replicasの2つに分類され、各ドキュメントはどれか1つのPrimary Shardに属しています。Replicas ShardはPrimary Shardのコピーで、何らかの障害が起こった際にPrimaryに昇格したり、ドキュメントを検索する際に利用します。

Blog Indexを作成した場合、 shard1_p shard2_p shard3_pのPrimary Shardにデータは分散して登録され、別NodeにはReplicas Shardが作成されます。どのNodeにどのShardを作成するかは、Elasticsearchが判断してくれます。

Primary ShardはIndex作成時に数を指定することが可能ですが、それ以降の変更は出来ません。Replicas Shardは途中で変更することが出来て、パフォーマンスに影響を与えずに追加することが可能です。

Primary ShardはIndex作成時に以下の値を設定してShard数を指定します。

PUT blog
{
    "settings" : {
        "number_of_shards" : 3,
        "number_of_replicas" : 3
    }
}

Indexの操作について

今までの記事で扱ってきたIndexについて、今回の構成を絡めてどのような流れでデータが操作されているのかをまとめてみました。 わかりやすいようにCoordinating Node専用NodeとしてNode4を追加してます。

  1. リクエストを受け取ったCoordinating Nodeは、該当DocumentをどのShardに保存するかを _id のハッシュ値をShard数で割り計算
  2. Shardを割り出したらNode3に対してリクエストを送信
  3. Node3はshard3_pに保存
  4. Replicas Shardを保持している、Node2に対しても同期
  5. 全ての処理が終わったらNode4に登録が完了したことを伝える
  6. Node4はIndexが正常に完了したことをレスポンス

Shardの項目に記載したように、利用者からIndexは1つに見えますが実態は各Shardに分散して保存されています。 では、その際にどのようにして保存先のShardを決めるかというと、Documentの _id(デフォルト)_routing のハッシュ値を計算して、プライマリーシャード数で割って求めます。

UpdateやDelete操作も上記の流れと同様です。Documentを保持しているShardに対して更新や削除を行います。

最後に

今回はElasticsearchのClusterやNode等の構成について勉強してみました。

次回は集計やページング等、様々な検索方法について書こうと思います。