既存のDroongaクラスタについて、新しいreplicaを追加し、既存のreplicaを削除し、および、既存のreplicaを新しいreplicaで置き換えるための手順を学ぶこと。
catalog.json
にsystem
プラグインが登録済みであること。
未登録の場合は、以下のようにしてplugins
の一覧にsystem
を追加しておいて下さい:
- "plugins": ["groonga", "crud", "search", "dump"],
+ "plugins": ["groonga", "crud", "search", "dump", "system"],
Droongaのノードの集合には、「replica」と「slice」という2つの軸があります。
「replica」のノード群は、完全に同一のデータを持っており、検索などのリクエストを各ノードが並行して処理する事ができます。 新しいreplicaを追加する事によって、増加するリクエストに対して処理能力を増強することができます。
他方、「slice」のノード群はそれぞれ異なるデータを持ちます(例えば、あるノードは2013年のデータ、別のノードは2014年のデータ、という具合です)。 新しいsliceを追加する事によって、増大するデータ量に対してクラスタとしての容量を拡大することができます。
現在の所、Groonga互換のシステムとして設定されたDroongaクラスタについては、replicaを追加することはできますが、sliceを追加することはできません。 この点については将来のバージョンで改善する予定です。
ともかく、このチュートリアルでは既存のDroongaクラスタに新しいreplicaを追加する手順を解説します。 早速始めましょう。
このケースでは、検索のように読み取りのみを行うリクエストに対しては、クラスタの動作を止める必要はありません。 サービスを停止することなく、その裏側でシームレスに新しいreplicaを追加することができます。
その一方で、クラスタへの新しいデータの流入は、新しいノードが動作を始めるまでの間停止しておく必要があります。 (将来的には、新しいノードを完全に無停止で追加できるようにする予定ですが、今のところはそれはできません。)
ここでは、192.168.0.10
と 192.168.0.11
の2つのreplicaノードからなるDroongaクラスタがあり、新しいreplicaノードとして 192.168.0.12
を追加すると仮定します。
まず、新しいコンピュータをセットアップし、必要なソフトウェアのインストールと設定を済ませます。
(on 192.168.0.12)
# apt-get update
# apt-get -y upgrade
# apt-get install -y ruby ruby-dev build-essential nodejs nodejs-legacy npm
# gem install droonga-engine
# npm install -g droonga-http-server
新しいノードには、クラスタの既存のノードから catalog.json
をコピーする必要があります。
(on 192.168.0.12)
# mkdir ~/droonga
# scp 192.168.0.10:~/droonga/catalog.json ~/droonga/
注意点として、空でないノードを既存のクラスタに追加することはできません。 もしそのコンピュータがかつてDroongaノードとして使われていた事があった場合には、最初に古いデータを消去する必要があります。
(on 192.168.0.12)
# kill $(cat $PWD/droonga-engine.pid)
# rm -rf ~/droonga
# mkdir ~/droonga
# scp 192.168.0.10:~/droonga/catalog.json ~/droonga/
では、サーバを起動しましょう。
(on 192.168.0.12)
# cd ~/droonga
# host=192.168.0.12
# DROONGA_BASE_DIR=$PWD
# droonga-engine --host=$host \
--log-file=$DROONGA_BASE_DIR/droonga-engine.log \
--daemon \
--pid-file=$DROONGA_BASE_DIR/droonga-engine.pid
# env NODE_ENV=production \
droonga-http-server --port=10041 \
--receive-host-name=$host \
--droonga-engine-host-name=$host \
--cache-size=-1 \
--daemon \
--pid-file=$DROONGA_BASE_DIR/droonga-http-server.pid
この時点では、ノードの情報が catalog.json
に含まれていないため、この新しいノードはクラスタのノードとしては動作していません。
新しいノードにリクエストを送っても、それらはすべてクラスタ内の既存のノードに転送されます。
この事は、system.status
コマンドの結果を見ると確認できます:
# curl "http://192.168.0.10:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
# curl "http://192.168.0.11:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
# curl "http://192.168.0.12:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
新しいreplicaとの間でデータを完全に同期する必要があるので、クラスタの構成を変更する前に、クラスタへのデータの書き込みを行うリクエストの流入を一時停止する必要があります。 そうしないと、新しく追加したreplicaが中途半端なデータしか持たない矛盾した状態となってしまい、リクエストに対してクラスタが返す処理結果が不安定になります。
データの書き込みを伴うリクエストとは、具体的には、クラスタ内のデータを変更する以下のコマンドです:
add
column_create
column_remove
delete
load
table_create
table_remove
cronjobとして実行されるバッチスクリプトによって load
コマンド経由で新しいデータを投入している場合は、cronjobを停止して下さい。
クローラが add
コマンド経由で新しいデータを投入している場合は、クローラを停止して下さい。
あるいは、クローラやローダーとクラスタの間にFluentdを置いてバッファとして利用しているのであれば、バッファからのメッセージ出力を停止して下さい。
前項から順番にチュートリアルを読んでいる場合、クラスタに流入しているリクエストはありませんので、ここでは特に何もする必要はありません。
新しいreplicaノードを既存のクラスタに追加するには、いずれかの既存のノードもしくは新しいreplicaノードのいずれかにおいて、catalog.json
が置かれているディレクトリで、droonga-engine-join
コマンドを実行します:
(on 192.168.0.12)
# cd ~/droonga
# droonga-engine-join --host=192.168.0.12 \
--replica-source-host=192.168.0.10
--host
オプションで、その新しいreplicaノードのホスト名またはIPアドレスを指定して下さい。--replica-source-host
オプションで、クラスタ中の既存のノードの1つのホスト名またはIPアドレスを指定して下さい。catalog.json
が置かれたディレクトリで実行するか、もしくはそのディレクトリのパスを --base-dir
オプションで指定して下さい。コマンドを実行すると、自動的に、クラスタのデータが新しいreplicaノードへと同期され始めます。
データの同期が完了すると、ノードが自動的に再起動してクラスタに参加します。
すべてのノードのcatalog.json
も同時に更新され、この時点をもって、新しいノードは晴れてそのクラスタのreplicaノードとして動作し始めます。
この事は、system.status
コマンドの結果を見ると確認できます:
# curl "http://192.168.0.10:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
},
"192.168.0.12:10031/droonga": {
"live": true
}
}
}
さて、準備ができました。 すべてのreplicaは完全に同期した状態となっているので、このクラスタはリクエストを安定して処理できます。 cronjobを有効化する、クローラの動作を再開する、バッファからのメッセージ送出を再開する、などの操作を行って、クラスタ内のデータを変更するリクエストの流入を再開して下さい。
以上で、Droongaクラスタに新しいreplicaノードを無事参加させる事ができました。
Droongaノードは、メモリ不足、ディスク容量不足、ハードウェア障害など、様々な致命的な理由によって動作しなくなり得ます。 Droongaクラスタ内のノードは互いに監視しあっており、動作しなくなったノードに対してはメッセージの配送を自動的に停止して、動作しないノードがあってもクラスタ全体としては動作し続けるようになっています。 このような時には、動作していないノードを取り除く必要があります。
もちろん、他の目的に転用したいといった理由から、正常動作中のノードを取り除きたいと考える場合もあるでしょう。
ここでは、192.168.0.10
、192.168.0.11
、および 192.168.0.12
の3つのreplicaノードからなるDroongaクラスタが存在していて、最後のノード 192.168.0.12
をクラスタから取り除こうとしていると仮定します。
新しいreplicaノードを既存のクラスタから削除するには、クラスタ内のいずれかのノードの上で、catalog.json
が置かれたディレクトリにおいて droonga-engine-unjoin
コマンドを実行します:
(on 192.168.0.10)
# cd ~/droonga
# droonga-engine-unjoin --host=192.168.0.12
--host
オプションで、クラスタから削除するノードのホスト名またはIPアドレスを指定して下さい。catalog.json
が置かれたディレクトリで実行するか、もしくはそのディレクトリのパスを --base-dir
オプションで指定して下さい。すると、ノードがクラスタから自動的に離脱し、すべてのノードの catalog.json
も同時に更新されます。
これで、ノードはクラスタから無事離脱しました。
この事は、system.status
コマンドの結果を見ると確認できます:
# curl "http://192.168.0.10:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
# curl "http://192.168.0.11:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
# curl "http://192.168.0.12:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.11:10031/droonga": {
"live": true
}
}
}
ノードの置き換えは、上記の手順の組み合わせで行います。
192.168.0.10
と 192.168.0.11
の2つのノードからなるDroongaクラスタがあり、ノード 192.168.0.11
の動作が不安定になっていて、これを新しいノード 192.168.0.12
で置き換えようとしていると仮定します。
まず、不安定になっているノードを取り除きます。以下のようにしてクラスタからノードを離脱させて下さい:
(on 192.168.0.10)
# cd ~/droonga
# droonga-engine-unjoin --host=192.168.0.11
これで、ノードがクラスタから離脱しました。この事は system.status
コマンドで確かめられます:
# curl "http://192.168.0.10:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
}
}
}
次に、新しいreplicaを用意します。
必要なパッケージをインストールし、クラスタの既存のノードから catalog.json
をコピーして、サーバを起動します。
(on 192.168.0.12)
# cd ~/droonga
# scp 192.168.0.10:~/droonga/catalog.json ./
# host=192.168.0.12
# DROONGA_BASE_DIR=$PWD
# droonga-engine --host=$host \
--log-file=$DROONGA_BASE_DIR/droonga-engine.log \
--daemon \
--pid-file=$DROONGA_BASE_DIR/droonga-engine.pid
# env NODE_ENV=production \
droonga-http-server --port=10041 \
--receive-host-name=$host \
--droonga-engine-host-name=$host \
--cache-size=-1 \
--daemon \
--pid-file=$DROONGA_BASE_DIR/droonga-http-server.pid
そうしたら、そのノードをクラスタに参加させましょう。
(on 192.168.0.12)
# cd ~/droonga
# droonga-engine-join --host=192.168.0.12 \
--replica-source-host=192.168.0.10
最終的に、192.168.0.10
と 192.168.0.12
の2つのノードからなるDroongaクラスタができあがりました。
この事は、system.status
コマンドの結果を見ると確認できます:
# curl "http://192.168.0.10:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.12:10031/droonga": {
"live": true
}
}
}
# curl "http://192.168.0.12:10041/droonga/system/status"
{
"nodes": {
"192.168.0.10:10031/droonga": {
"live": true
},
"192.168.0.12:10031/droonga": {
"live": true
}
}
}
このチュートリアルでは、既存のDroongaクラスタに新しいreplicaノードを追加する方法を学びました。 また、既存のreplicaを取り除く方法と、既存のreplicaを新しいreplicaで置き換える方法も学びました。