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

第3回 Kaiの詳細(1) ─Kaiの要であるクラスタを極める

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

前回Kai のインストールと基本的な使い方を説明しましたので,今回は,Kai最大の特徴であるクラスタついて詳しく説明します。

なお,前回同様,本連載が対象とするKaiのバージョンは0.4,ErlangのバージョンはR13Bです。

データの保存・取得とリクエストの転送

memcachedでは,クライアントがデータの場所を決定します。このため,クライアントは,クラスタを構成するすべてのmemcachedノードを把握していなければなりませんでした。

一方Kaiでは,ノードがデータの場所を決定し,クライアントからのリクエストを適切なノードに転送します。クライアントは,すべてのノードを把握する必要がありませんし,L4ロードバランサで機械的に負荷分散することもできます。また,クラスタへノードが追加されても,クライアントのノード一覧を修正する必要がありません。

では,前回,構築した3ノード構成のクラスタへデータを保存・取得をする事で,リクエストの転送を試してみます。

次のようなPerl Scriptを用意し,kai_test_cluster.plという名前で保存してください。

リスト1 kai_test_cluster.pl

#!/usr/bin/env perl

use strict;
use warnings;

use Test::More tests => 3;
use Cache::Memcached;

my $set_only_mem = Cache::Memcached->new({
    servers => [map {'127.0.0.1:1121' . $_} (1..3)],
});

$set_only_mem->set(foo => 'bar', 0,); # Consistent Hashing により一つのノードを選択し,データを保存する

for (1..3) {
    my $get_only_mem = Cache::Memcached->new({
        servers => ['127.0.0.1:1121' . $_],
    });
    is $get_only_mem->get('foo'), 'bar'; # 全てのノードから同じ値が取得できる
}

memcachedと異なり,保存リクエストを送るノードと,取得リクエストを送るノードは,異なっていても構いません。前述の通り,クラスタ内で適切なノードに転送されます。

では,実行してみます。

$ perl /path/to/cluster_test.pl
1..3
ok 1
ok 2
ok 3

このような実行結果となれば,リクエストの転送が正常に行えています。

ノードの追加・除去による自動データ再配置

memcachedでは,ノードを追加・除去するとキャッシュミスが発生します。その場合,クライアントはデータをデータベースから再取得して,新しいデータ配置に従って保存し直します。

一方Kaiでは,データの永続性を保証するために,ノードの追加・除去を検知して,データを自動的に再配置します。クライアントは,除去されたノードへのアクセスを停止する以外に,何もすることはありません。もちろん,新たに追加されたノードからも,過去に保存したデータを取得できます。

では,先ほどのクラスタへ新たなノードを追加し,それらのノードから先ほど保存したデータが取得できるか試してみます。

まず始めに,kai4.configという設定ファイルを作成してください。

$ /path/to/make_kai_config.sh 4

続けて,新しいノードを起動します。

$ /path/to/start_kai.sh kai4

次に,新しいノードをクラスタへ参加させます。

$ /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}, 11014}).     % (a)
ok
(kai1@centos)2> kai_rpc:check_node({{127,0,0,1}, 11014}, {{127,0,0,1}, 11011}).     % (b)
ok
(kai1@centos)3>                  <- 作業が終わったので,local shell に切り替える
User switch command
 --> s
 --> c
Eshell V5.7.1  (abort with ^G)
(kai_controller@centos)1> q().
ok

前回は,説明を簡略化するため,クラスタ構成時のノード間通信の説明を省きました。しかし,クラスタを運用する際に必要となる知識であるため,ここで説明します。

まず (a) で,既にクラスタに参加しているノードkai1に,新たなノードkai4を確認しろと指示しています。すると,kai1はkai4へnode_listリクエストを送信します。

node_listリクエストを受信したノードは,送信元ノードに対して,自身を含む,自身が持つノードの一覧を返します。kai4は,自分自身の情報しか持たないため,kai1にはkai4の情報のみ返します図1 矢印1)。

各ノードは定期的に,ランダムに選んだノードとノード一覧を交換しているため,kai1が取得した情報はすぐにkai2,kai3へと伝わります図1 矢印2)。

最後に (b) で,kai4にkai1を確認しろと指示しています。すると,kai4はkai1にnode_listリクエストを送り,kai1からkai1,kai2,kai3の情報を受け取り図1 矢印3),クラスタが完成します。

図1 クラスタ {kai1,kai2,kai3} にノードkai4を追加する例

図1 クラスタ {kai1,kai2,kai3} にノードkai4を追加する例

著者プロフィール

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

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

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

コメント

コメントの記入