mixi engineer blog

*** 引っ越しました。最新の情報はこちら → https://medium.com/mixi-developers *** ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

Anuenueで検索クラスタを作る

研究開発グループの takahi-i です.

前回 Solr を利用した検索パッケージ Anuenue を紹介させていただきました. 今回は Anuenue を利用して目的に応じた検索クラスタを構成する方法について紹介させていただきます.

Anuenue (Solr) インスタンスは単体でもある程度高速に動作しますが, 大規模データ, 高い QPS に耐えるには複数のインスタンスからなる検索クラスタを構築する必要があります. Anuenue を利用してクラスタを構築するには Anuenue が提供する設定ファイルを目的にあわせて編集する必要があります.

Anuenue には重要な設定ファイルが三つ存在します. これらの設定ファイルは Anuenue のインストールディレクトリ (ANUENUE_HOME) 直下の conf ディレクトリに存在します. 以下 Anuenue の設定ファイルの名前を列挙しました.

  1. schema.xml
  2. anuenue-env.sh
  3. anuenue-nodes.xml

ではそれぞれの設定ファイルについて説明させていただきます.

schema.xml

scheme.xml は Solr が提供する設定ファイルでインデクスの構成を記述します. Anuenue でもこのファイルを利用して作成するインデクスの構成を記述します. くわしい編集方法については Solr の解説ページを参照してください.

anuenue-env.sh

anuenue-env.sh は Anuenue のインスタンス単位の基本的な設定項目を提供します. 特に JAVA_HOME は起動するために必ず設定が必要な項目です. また そのほかにキャッシュサイズなどのチューニングパラメタ用の変数なども提供されています.

具体的な設定項目については Configuraiton ページを参照してください. この設定ファイルは起動時に他のインスタンスにコピーされます. クラスタの起動方法については後述します.

もしクラスタ内の個々のインスタンスで違う設定をしたい場合 (たとえばMergerインスタンスと Slave インスタンスで別々のキャッシュサイズを持たせる場合) は各インスタンスの conf ディレクトリにある anuenue-env-site.sh を編集してください. 二つのファイルは同一の設定項目を持ちますが, anuenue-env-site.sh の設定が常に優先されます.

anuenue-nodes.xml

この設定ファイルはクラスタ内の各インスタンスに Role (役割) を付与するために利用します. Role については前回お話したとおり Merger, Master, Slave の3つがあります. 復習しますとそれぞれ以下の役割を持ちます.

Master, Slave, Merger

  1. Merger - クライアントから発行されたクエリをSlaveインスタンスに転送し, Slaveインスタンスから帰ってきた結果をマージしてクライアントに返す.
  2. Master - 入力データをインデクスする.
  3. Slave - インデクスをMasterインスタンスからコピーする. Mergerインスタンスからクエリが転送されてきた際には自身のインデクスを検索し結果をMergerインスタンスに返す.

例: Anuenueを用いた検索クラスタ

検索クラスタを構成するのに使用する計算機が10台存在して, 各計算機に Anuenue インスタンスがインストールされているとします. このクラスタでは二つの Merger ("Merger-1", "Merger2"), 四つの Master ("Master-1", "Master-2", "Master-3", "Master-4") があり, Master のインデクスをコピーする Slave が同じく四台 ("Slave-1", "Slave-2", "Slave-3", "Slave-4") という構成です. 以下 Anuenue クラスタの構成例のイメージです.

 

このクラスタは以下のように動作します. はじめに本クラスタ内の Master インスタンスは入力データからインデクスを生成します (
インデクスの生成には後述する Anuenue が提供するコマンドを使用します). Master インスタンスで生成されたインデクスは Slave インスタンスにコピーされ, データは検索可能な状態になります.

クライアントは二つある Merger のどちらかにクエリを発行し, Merger は四つある Slave インスタンスにクエリを転送します. クエリを受け取った Slave は自身のインデクスを検索したのち, クエリを転送した Merger に結果を返します. Merger は各 Slave から返された結果をマージしてクライアントに返します.

anuenue-nodes.xml の編集

anuenue-nodes.xml は三つの要素 (masters, mergers, slaves) を持ちます. 各要素にクラスタに含まれるインスタンス情報を加えます. インスタンス情報はホスト名とポート番号です. 以下 anuenue-nodes.xml の一部です. このファイルは検索クラスタには二つの Master インスタンスが存在し, そのインスタンスは計算機 "aaaa" と "bbbb" に存在することを表します.

<masters>
    <master>
      <host>aaaa</host>
      <port>8983</port>
    </master>
    <master>
      <host>bbbb</host>
      <port>8983</port>
    </master>
  </masters>

Slave インスタンスを追加するには "replicate" 要素を追加する必要があります. replicate 要素でインデクスをコピーする先の Masterインスタンスを指定します. 具体的には Master インスタンスを指定するために "iname" アトリビュートで名前を付与し, 付与された名前を Slave インスタンスの replicate 要素に追加します. この設定を追加することで, Slaveインスタンスは指定された Master インスタンスのインデクスを監視し, 変更がコミットされた時点で Master のインデクスのコピーを開始します. たとえば二つのインスタンスが "aaaa" と "bbbb" という計算機に存在し, "aaaa"上のインスタンスが Master で "bbbb" 上のインスタンスが Slave だったとします. この時, 以下のように anuenue-nodes.xml (一部) を記述します. この XML ファイルから Slave インスタンス ("bbbb") が Master インスタンス ("aaaa") を付与した名前 (iname) を通じて参照していることが分かります.

<masters>
    <master iname="master">
      <host>aaaa</host>
      <port>8983</port>
    </master>
  </masters>
  <slaves>
    <slave>
      <host>bbbb</host>
      <port>8983</port>
      <replicate>master</replicate>
    </slave>
  </slaves>

例:anuenue-nodes.xml

それでは以下の anuenue-nodes.xml からどのようなクラスタが生成されるのかについてお話しします.

<?xml version='1.0'  encoding='utf-8'?>
<nodes>
  <mergers>
    <merger>
      <host>aaaa</host>
      <port>8983</port>
    </merger>
  </mergers>
  <masters>
    <master iname="master1">
      <host>bbbb</host>
      <port>8983</port>
    </master>
    <master iname="master2">
      <host>cccc</host>
      <port>8983</port>
    </master>
  </masters>
  <slaves>
    <slave>
      <host>dddd</host>
      <port>8983</port>
      <replicate>master1</replicate>
    </slave>
    <slave>
       <host>eeee</host>
       <port>8983</port>
       <replicate>master2</replicate>
    </slave>
  </slaves>
</nodes>

ここで "aaaa", "bbbb", "cccc", "dddd", "eeee" という計算機が手元にあり, そのすべてに Anuenue がインストールされていることを仮定します. このクラスタ上で "aaaa" は Merger でユーザからのクエリを受け付けます. "bbbb" と "cccc" 上の Anuenue は Master インスタンスで, 入力データをインデクスします. "dddd" と "eeee" は Slave インスタンスでそれぞれインデクスを "bbbb" と "cccc" からコピーします.

以下がこの anuenue-nodes.xml から生成される検索クラスタのイメージです.

 

高度な設定

Anuenue は設定を追加することで以下のようなクラスタを構築することができます。使用用途によっては便利な機能なので是非ご検討ください。

複数のRoleを付与する

Anuenue では一つのインスタンスに複数の Role を付与することでクラスタに必要な計算機の数を低減できます. 以下の例は二つのインスタンスが Merger, Slave, Master のすべてのRole を付与されています.

Slaveインスタンスでグループを形成する

また Master のインデクスを Slave インスタンス集合でグループを形成することでよりQPSが高い環境に対応できます. この時Mergerは複数あるSlaveグループのうちの一つにクエリをランダムで転送します. 例えば下記のクラスタでは "dddd" と "eeee" からなるグループ (Group 1) と "ffff" と "gggg" からなるグループ (Group 2) の二つのグループが存在し, 各グループは同一のインデクスを持ちます.

本節で述べたクラスタの具体的な設定方法については Anuenue の Configuration ページを参照してください.

設定が終わった後

今まで検索クラスタの設定方法についてお話ししてきました. 設定ファイルの編集が終わったら, 実際にクラスタを立ち上げます. なお設定ファイルはクラスタ内のどれかのインスタンスで設定して, 設定ファイルを編集したインスタンスの ANUENUE_HOME ディレクトリから以下のコマンドでクラスタを起動します.

$sh bin/anuenue-distdaemon.sh start

次にインデクスを生成します. インデクスの生成には以下のコマンドをクラスタ内のインスタンス上の ANUENUE_HOME ディレクトリで実行します.

$sh bin/anuenue-distcommands post --arg input-data

提供するすべてのコマンドはマルチスレッドで動作するのでそこそこのスピードでインデクスを行えます. 入力の input-data は入力対象のデータを schema.xml にあわせてご自身で生成する必要があります. 具体的なフォーマットについては Anuenue のヘルプページを参照してください. クラスタが立ち上がっているかどうかは Anuenue の Admin UI ページにアクセスすることで分かります. UIページは http://merger-instance/anuenue/admin です. 以下 Admin UI の画面です.

インデクスの生成が終わりコミットコマンドを実行すると, Masterにある各インデクスはSlaveにコピーされます. 以下コミットコマンドです.

$sh bin/anuenue-distcommands.sh commit

インデクスがコピーされた後, 入力データはクライアントから検索できます.

まとめとご報告

今回は Anuenue の設定とクラスタの構成方法について説明させていただきました. 現在までに Anuenue は mixi ページの検索に無事導入されました.