はじめに
Solr vs ElasticSearchな今日この頃ですが、SolrCloudでのレプリケーション環境構築を試してみました。
「solr -e cloud」で同一サーバー上にexampleのSolrCloud環境は簡単に構築できるのですが、具体的に何をやっているのかよくわからないので、複数サーバーで実際に使うであろう手順を踏んでの構築を試みてました。
先に感想としては、RDBMSでMaster-Slaveでのレプリケーション環境はよく構築していましたが、SolrCloudではZooKeeperを用いてのレプリケーション、フェールオーバー、ノーダーノード自動選出など中央集中管理が非常に魅力的だな感じました。それとドキュメントが充実していてわかりやすいのがいいですね。
今回、SolrCloudで構築したい全体像
今回は最小のクラスタ構成を構築してみるという趣旨で、シャード、ノード、Zookeeperをそれぞれ2つずつ。(Zoopkeeperの構築については省略してます)
構築環境
今回試す環境は以下の通り。
- OS X EI Capitan 10.11.4
- Vegrant 1.8.1
- VirtualBox 5.0.16
- Ansible
- Ubuntu ubuntu 14.04
- Solr 6.0
- ZooKeeper 3.4.8
- Java 1.8.0
1. ノードを作成
192.168.33.10にノード1を作成
まずはノード1を作成。ポートは8001を指定します。
$ sudo mkdir -p myserver/node1/solr
$ sudo cp server/solr/solr.xml myserver/node1/solr/
$ sudo solr start -cloud -s /opt/solr/myserver/node1/solr -p 8001 -z 192.168.33.20:2181,192.168.33.21:2181 -h 192.168.33.10
192.168.33.10にノード2を作成
同様にノード2も作成。ポートは8002を指定します。
$ sudo mkdir -p myserver/node2/solr
$ sudo cp server/solr/solr.xml myserver/node2/solr/
$ sudo solr start -cloud -s /opt/solr/myserver/node2/solr -p 8002 -z 192.168.33.20:2181,192.168.33.21:2181 -h 192.168.33.10
192.168.33.11にノード3を作成
まずはノード3を作成。ポートは8003を指定します。
$ sudo mkdir -p myserver/node3/solr
$ sudo cp server/solr/solr.xml myserver/node3/solr/
$ sudo solr start -cloud -s /opt/solr/myserver/node3/solr -p 8003 -z 192.168.33.21:2181,192.168.33.21:2181 -h 192.168.33.11
192.168.33.11にノード4を作成
同様にノード4も作成。ポートは8004を指定します。
$ sudo mkdir -p myserver/node4/solr
$ sudo cp server/solr/solr.xml myserver/node4/solr/
$ sudo solr start -cloud -s /opt/solr/myserver/node4/solr -p 8004 -z 192.168.33.21:2181,192.168.33.21:2181 -h 192.168.33.11
2. コレクションの作成
最小構成でシャード2 x レプリケーション2でコレクションを作成してみます。
サンプルデータを挿入したいので「configsets」はスキーマーレスな「data_driven_schema_configs」を選びます。
$ solr create_collection -c testcollection -d server/solr/configsets/data_driven_schema_configs -p 8001 -shards 2 -replicationFactor 2
管理画面にアクセスして下記のように表示されればOK。現時点ではノードは一つもありません。
http://192.168.33.10:8001/solr/#/~collections/testcollection
Cloud > Graphを見てもまだ何も表示されません。
3. クラスタ構築
コレクションとノードの紐付けはGUI上でもできますが(「add replica」をクリックすれば)、今後なるべく自動化していきたいので、コマンドライン上での紐付けを試してみます。
$ curl -XGET "http://192.168.33.10:8001/solr/admin/collections?action=ADDREPLICA&collection=testcollection&shard=shard1&node=192.168.33.10:8001_solr"
$ curl -XGET "http://192.168.33.10:8001/solr/admin/collections?action=ADDREPLICA&collection=testcollection&shard=shard2&node=192.168.33.10:8002_solr"
$ curl -XGET "http://192.168.33.10:8001/solr/admin/collections?action=ADDREPLICA&collection=testcollection&shard=shard1&node=192.168.33.11:8003_solr"
$ curl -XGET "http://192.168.33.10:8001/solr/admin/collections?action=ADDREPLICA&collection=testcollection&shard=shard2&node=192.168.33.11:8004_solr"
無事、冗長構成が出来上がりました。
4. 検索テスト
テストデータを流し込んで、データを取得してみます。
$ sudo ./bin/post -c testcollection -host 192.168.33.10 -p 8001 example/exampledocs/books.json
シャード1のデータを見てみます。ドキュメントが1つ見つかりました。リクエストパラメーターに「shards=shard1」と入れることでシャードの指定ができます。
$curl "http://192.168.33.10:8001/solr/testcollection/select?indent=on&q=*:*&wt=json&shards=shard1"
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":32,
"params":{
"q":"*:*",
"shards":"shard1",
"indent":"on",
"wt":"json"}},
"response":{"numFound":1,"start":0,"maxScore":1.0,"docs":[
{
"id":"978-0641723445",
"cat":["book",
"hardcover"],
"name":["The Lightning Thief"],
"author":["Rick Riordan"],
"series_t":["Percy Jackson and the Olympians"],
"sequence_i":1,
"genre_s":"fantasy",
"inStock":[true],
"price":[12.5],
"pages_i":384,
"_version_":1533160426202726400}]
}}
続いてシャード2。ドキュメントが3つ見つかりました。
$ curl "http://192.168.33.10:8001/solr/testcollection/select?indent=on&q=*:*&wt=json&shards=shard2"
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":0,
"params":{
"q":"*:*",
"shards":"shard2",
"indent":"on",
"wt":"json"}},
"response":{"numFound":3,"start":0,"docs":[
{
"id":"978-1423103349",
"cat":["book",
"paperback"],
"name":["The Sea of Monsters"],
"author":["Rick Riordan"],
"series_t":["Percy Jackson and the Olympians"],
"sequence_i":2,
"genre_s":"fantasy",
"inStock":[true],
"price":[6.49],
"pages_i":304,
"_version_":1533160426197483520},
{
"id":"978-1857995879",
"cat":["book",
"paperback"],
"name":["Sophie's World : The Greek Philosophers"],
"author":["Jostein Gaarder"],
"sequence_i":1,
"genre_s":"fantasy",
"inStock":[true],
"price":[3.07],
"pages_i":64,
"_version_":1533160427078287360},
{
"id":"978-1933988177",
"cat":["book",
"paperback"],
"name":["Lucene in Action, Second Edition"],
"author":["Michael McCandless"],
"sequence_i":1,
"genre_s":"IT",
"inStock":[true],
"price":[30.5],
"pages_i":475,
"_version_":1533160427141201920}]
}}
・Distributed Search with Index Sharding:
https://cwiki.apache.org/confluence/display/solr/Distributed+Search+with+Index+Sharding
5. フェールオーバーのテスト
現在のクラスタの状態です。shard1、shard2ともに192.168.33.11がリーダー(黒丸)となっています。その192.168.33.11がサーバーごとぶっ飛んだ場合でも正しくデータを取得できるかを試してみます。
vagrantで強制終了・・。haltをポチッと。
$ vagrant halt
停止した192.168.33.11がグレーアウトしてリーダーが33.10に変わったことがわかります。
この状態でもう一度データ検索してみます。
シャード1。
$ curl "http://192.168.33.10:8001/solr/testcollection/select?indent=on&q=*:*&wt=json&shards=shard1"
....
"response":{"numFound":1,"start":0,"maxScore":1.0,"docs":[
....
シャード2。
$ curl "http://192.168.33.10:8001/solr/testcollection/select?indent=on&q=*:*&wt=json&shards=shard2"
....
"response":{"numFound":3,"start":0,"maxScore":1.0,"docs":[
....
シャードの指定をしなかった場合。
$ curl "http://192.168.33.10:8001/solr/testcollection/select?indent=on&q=*:*&wt=json"
....
"response":{"numFound":4,"start":0,"maxScore":1.0,"docs":[
....
無事、取得できました。
実稼働するにはまだ調査・検証しなければいけないことがたくさんありますが、とりあえずは簡易的なクラスタ構成で基本的な動作のみを試してみました。冒頭にもあげましたが、ドキュメントがわかりやすく、APIも使いやすいので、比較的導入しやすいのではと思いました。(もちろん、大変なことは多々あるでしょうが・・)
参考サイト・書籍
- SolrCloud
SolrCloud公式ドキュメント。
https://cwiki.apache.org/confluence/display/solr/SolrCloud
- Collections API
コレクションを操作したい場合は下記URL参照。
https://cwiki.apache.org/confluence/display/solr/Collections+API