分散Key/Valueストア,Kaiを使ってみよう!

第2回 Kai の基礎 ─Kaiのインストールと基本的な使い方

この記事を読むのに必要な時間:およそ 7.5 分

Erlang VMのコンソールをDetacheする

今のままでは,Erlang VMのコンソールを終了するとKaiも終了してしまい,少々使い難いため,Erlang VMのコンソールをDetacheしてバックグラウンドで動作させる方法を説明します。

erlコマンドには,-sname,-detached,-remsh という引数があり,これらを使用してErlang VMの操作を行います。

それぞれの引数の意味は次のとおりです。

引数説明
-snameErlangノードの名前を指定できます。名前を付ける事で,DetacheしてしまったErlang VMのコンソールを操作できます。
-detachedErlang VM起動後,すぐにコンソールをDetacheします。必ず-snameと共に使用する必要があります。
-remsh操作する対象のErlangノードの名前を指定できます。-detachedと同様に-snameと共に使用する必要があります。

では,Kaiをバックグラウンドで動作させてみましょう。

次のコマンドを実行すると,Kaiを起動後すぐにErlang VMのコンソールをDetacheします。

$ erl -sname kai -pa ebin -config kai -eval 'application:start(kai).' -detached

-sname kaiを指定すると,kai@`hostname -s` という名前がErlangノードに付きます。筆者の環境では,hostname -sの結果がcentosであるため,kai@centosという名前が付きました。

毎回,このようなコマンドを実行するのは効率が悪いため,次のような起動スクリプトを作成しておくと便利です。

この起動スクリプトをstart_kai.shという名前で保存してください。

リスト5 start_kai.sh

#!/bin/sh

ROOT='/path/to/kai-0.4.0'
ERL='/usr/bin/env erl'

for n in $@
do
${ERL} -sname ${n} \
       -pa ${ROOT}/ebin \
       -config ${ROOT}/${n} \
       -eval 'application:start(kai).' \
       -detached
done

変数ROOTには,Kaiをコンパイルしたディレクトリをフルパスで指定してください。フルパスで指定する事により,任意のでディレクトリで起動スクリプトを実行できるようになります。

起動スクリプトの第一引数は,Erlangノード名だけではなく,読み込む設定ファイルも指定している点に注意してください。

次に,バックグラウンドで動作するKaiを停止してみましょう。次のコマンドを実行すると,Erlangノード "kai@centos" に接続し,終了コマンドを送信します。

$ erl -sname kai_controller -remsh kai@centos
Erlang R13B (erts-5.7.1) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(kai@centos)1> q().      <- プロンプトが接続元 kai_controller@centos ではなく,接続先となる事に注意
ok
(kai@centos)2>
User switch command      <- q(). で接続先が終了してしまい,コンソールが操作できない為,Ctrl+G でメニューを呼び出す
 --> q                   <- q で kai_controller@centos を終了させる

このコマンドもスクリプトにしておくと便利です。erlコマンドの引数に習って,remsh.shという名前で保存してください。

リスト6 remsh.sh

#!/bin/sh

ERL='/usr/bin/env erl'

${ERL} -sname kai_controller -remsh $1@`hostname -s`

なお,これらの運用に関する詳細な説明は,本連載の最後で橋本さんにより解説される予定です。

クラスタを構築する

Kaiは,複数のノードでクラスタを構築し,データを複製して保持する事ができます。

今回は,気軽にお試しいただけるよう,一台の物理マシン上で複数のノードを起動する事でクラスタを構築しますが,複数台の物理マシンでクラスタを構築する方法も基本は同じです。

ここでは,3ノード構成のクラスタの例を説明します。

まず始めに,ノードごとに設定ファイルを準備する必要があるのですが,設定ファイルを作る度にエディタを起動するのは効率が悪いので,次のようなヘルパースクリプトを作成しmake_kai_config.shという名前で保存してください。

リスト7 make_kai_config.sh

#!/bin/sh

for n in $@
do
cat <<__END_OF_CONFIG__ > kai${n}.config
[{kai, [
    {rpc_port, 1101${n}},
    {rpc_max_processes, 30},
    {memcache_port, 1121${n}},
    {memcache_max_processes, 10},
    {max_connections, 32},
    {n, 3},
    {r, 2},
    {w, 2},
    {number_of_buckets, 1024},
    {number_of_virtual_nodes, 128},
    {store, ets}
]}].
__END_OF_CONFIG__
done

次に,このヘルパースクリプトを使用して,ノードごとにkai1.config,kai2.config,kai3.configという名前の設定ファイルを作成します。

$ /path/to/make_kai_config.sh 1 2 3

スタンドアローンの例とは異なり,Quorumに設定するの値がデフォルトのN:R:W = 3:2:2に戻っている点と,全てのノードが一台の物理マシン上で起動するため,Listenするポート番号を変更してある点に注意してください。

また,今回は全てのノードがストレージとしてetsを指定していますが,各ノード毎に指定するストレージは任意であるため,用途にあわせて自由に設定してください。

次に,3つのノードを起動します。

$ /path/to/start_kai.sh kai1 kai2 kai3

このままでは,それぞれのノードが個々にスタンドアローンで起動している状態ですので,それぞれのノードに互いの存在を教えてクラスタを構築します。

あるノードAに,あるノードBの存在を教えるErlangの式は,"kai_rpc:check_node(NodeA, NodeB)" となります。

NodeA,NodeBは,"{IPAddress, Port}" という形式,IPAddressは,"{127,0,0,1}" という形式で指定します。なお,アドレスの区切りが "."(ドット)ではなく "," ⁠カンマ)である点に注意してください。

$ /path/to/remsh.sh kai1
Erlang R13B (erts-5.7.1) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(kai1@centos)1> kai_rpc:check_node({{127,0,0,1}, 11011}, {{127,0,0,1}, 11012}).
ok
(kai1@centos)2> kai_rpc:check_node({{127,0,0,1}, 11012}, {{127,0,0,1}, 11013}).
ok
(kai1@centos)3> kai_rpc:check_node({{127,0,0,1}, 11013}, {{127,0,0,1}, 11011}).
ok
(kai1@centos)4>

「ここでは,kai1に接続し,クラスタの構築を行いましたが,kai2やkai3に接続しても同様の事が行えます。

最後に,それぞれのノードが互いの情報を保持しているのか確認します。あるノードAが保持しているノードの一覧を取得するErlangの式は,"kai_rpc:node_list({IPAddress, Port})" となります。

(kai1@centos)4> kai_rpc:node_list({{127,0,0,1}, 11011}).
{node_list,[{{192,168,1,2},11012},
            {{192,168,1,2},11011},
            {{192,168,1,2},11013}]}
(kai1@centos)5> kai_rpc:node_list({{127,0,0,1}, 11012}).
{node_list,[{{192,168,1,2},11012},
            {{192,168,1,2},11011},
            {{192,168,1,2},11013}]}
(kai1@centos)6> kai_rpc:node_list({{127,0,0,1}, 11013}).
{node_list,[{{192,168,1,2},11012},
            {{192,168,1,2},11011},
            {{192,168,1,2},11013}]}
(kai1@centos)7>
User switch command
 --> q

このように,一つのノードが,自身も含めたクラスタを構成する全てのノード情報を保持していれば,クラスタの構築は終わりです。

次回の予告

以上で,Kaiを活用するための下準備ができました。

次回は,いよいよ他のKey/Valueストアと一線を画するクラスタの詳細を説明する予定です。どうぞご期待ください。

著者プロフィール

幾田雅仁(いくたまさひと)

酪農,ゴルフのキャディさん,某大手パソコン通信の下請け,某大手ポータルサイトなどを経て,決済代行を生業とする株式会社ゼロに入社。

p2p?なにそれ?美味しいの?の状態で,Erlang 分散処理勉強会に参加し,Kai のプレゼンを見て感銘を受け,無理矢理開発に参加し,現在に至る。