Solrのインデックスデータを他のサイトへレプリケーションする | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

Solrのデータの取り込み・インデックス作成は実行コストがかなり大きく、実行中に検索サービスが正常に提供できないことがあったりします。

そういった事態を避けるために、Solrのデータ管理を分散し、マスターにてデータ更新を行い、その反映データをスレーブにすばやく反映するためのレプリケーション機能がSolrには標準で用意されています。


Solrが差分の更新をうまくしてくれるので、データの取り込みをするよりレプリケーション機能を使った方がかなり高速にデータの反映が行えます。



Apache Solrでレプリケーションを利用する(マスターサイト設定)


ここではまず、レプリケーション機能を使うために2つのサイトを用意します。

1つ目がマスターサイトでデータの更新管理を行うサーバーになります。

もう一方がスレーブサイトで、基本的にマスターサイトからの更新データを受け取って反映するだけのサイトにはなりますが、サービス提供はスレーブ側で行います。

データの流れは常にマスターからスレーブに行うので、スレーブサイトでのデータ更新は行わず、ある意味Read Onlyで運用するイメージとなります。


まずは、マスターサイトでSolrの設定ファイル(solrconfig.xml)にて、レプリケーション時の挙動やレプリケーション対象の各種ファイルを設定します。

該当箇所は初期値ではコメントアウトされているのでコメントアウトを解除し、適宜編集します。


<requestHandler name="/replication" class="solr.ReplicationHandler" >
  <!--
     To enable simple master/slave replication, uncomment one of the
     sections below, depending on whether this solr instance should be
     the "master" or a "slave".  If this instance is a "slave" you will
     also need to fill in the masterUrl to point to a real machine.
  -->
     <lst name="master">
       <str name="replicateAfter">commit</str>
       <str name="replicateAfter">startup</str>
       <str name="replicateAfter">optimize</str>
       <str name="confFiles">schema.xml,stopwords.txt,mapping.txt,synonyms_index.txt,synonyms_query.txt,lang/userdict_ja.txt</str>
     </lst>
</requestHandler>

replicateAfterの設定は、レプリケーションを行うタイミングを指定します。

それぞれ、コミット時、Solr起動時、最適化実行時にレプリケーションが行われます。

ただし、レプリケーションをキックするのはスレーブ側で、そのレプリケーションタイミングはチェックする間隔を指定できるので、そのタイミングが来たときにマスター側で設定したレプリケーションすべきかどうかの判断基準を元に実行されるようです(後述)。


confFilesの設定は、インデックスデータのレプリケーションと一緒に同期する設定ファイルを記述しておきます。

これにより、マスター側でスキーマ情報(schema.xml)が変わったり、辞書データ(userdict_ja.txt)を変更してもスレーブ側に同時に反映させることが可能です。



Apache Solrでレプリケーションを利用する(スレーブサイト設定)


マスター側の設定が終わったら次はスレーブ側の設定です。

スレーブ側のSolrからマスターのデータを取りに行くので実質スレーブは幾つでも作ることができます。

スレーブ側の設定ファイルもマスターと同様にsolrconfig.xmlを編集します。


<requestHandler name="/replication" class="solr.ReplicationHandler" >
  <!--
     To enable simple master/slave replication, uncomment one of the
     sections below, depending on whether this solr instance should be
     the "master" or a "slave".  If this instance is a "slave" you will
     also need to fill in the masterUrl to point to a real machine.
  -->
     <lst name="slave">
       <str name="masterUrl">http://master.example.com:8983/solr/collection</str>
       <str name="pollInterval">08:00:00</str>
     </lst>
</requestHandler>

masterUrlにて、マスター側のSolrのコレクションへのURLを指定します。

pollIntervalは同期をキックする時間間隔です。

この場合、8時間ごとにマスターサイトに変更があるかチェックし、変更がある場合は同期が開始されます。


もし、マスター側のSolrにBasic認証をかけている場合は、上記に


<str name="httpBasicAuthUser">Username</str>
<str name="httpBasicAuthPassword">Password</str>

を追加します。

セキュリティのためのApache Solrアクセス制限あれこれ 」に書いたようにマスターとスレーブ側で接続を許可するIPアドレスを追加して互いに信頼関係を設定しておいた方がよいかもしれませんが。



マスターとスレーブのデータを同期する


設定が完了したら早速レプリケーションを実行してみます。

まずは、マスター側のSolr管理サイトから設定が正しくできているか確認してみます。

管理サイトへアクセスし、左メニューからコレクションを選択してReplicatonメニューを開きます。


SolrReplication-1


レプリケーションのタイミングや同期する設定ファイルなど、設定した内容が正しく表示されていれば問題ありません。

次に、スレーブ側の管理サイトを開きます(同じReplicationメニューです)


SolrReplication-2


スレーブ側では、設定内容だけでなくレプリケーションの状況なども表示されます。

レプリケーションは、スレーブ側で設定した同期の間隔(pollInterval)でチェックされ、マスター側に変更が加わっていた場合(で、replicateAfterの要件が満たされている)に同期されます。

同期の間隔は左上に「Next Run」としてカウントダウン表示されていますので、次の同期のタイミングもわかります。

すぐに同期したい場合は、その下の「Replicate now」ボタンをクリックすると同期がすぐに開始されます。

ただ、どうも指定の時間にレプリケーションを実行するという機能は無いみたいです。

ですので、例えばサービスに影響が少ない深夜3時にレプリケーションをしたいという場合は、その時間帯に管理サイトから手動でレプリケーションを実行するか、同期間隔をうまいこと3時に実行するように調整して、その後に実行間隔を24時間ごとに変更するといった工夫が必要そうです。


同期のステータスは一番上の「Iterations」の項目に表示され、展開するとレプリケーションを何時実行し、それが成功したのか失敗したのかがわかります。

または、その下にマスターとスレーブのVersionやGen、Sizeの項目の数字が一致していればデータも揃っているという確認になります。


初回の同期は、全てのデータが転送されるためそれなりに時間がかかりますが、次回以降は差分での更新になるため、かなり高速にデータが同期されます(もちろん、マスター側でデータの全消し・全投入のようなことをした場合は、レプリケーションに時間がかかることになってしまうでしょうけど)。


設定もかなり簡単に行えますし、ユーザーへのサービス提供とデータ更新の管理作業を分散できるので、バックアップの意味だけでなく、レプリケーション機能を活用した方がサービスを提供しやすいかと思います。