日本OSS推進フォーラム 若手技術者勉強会

目次

1. ハンズオンの概要

このハンズオンは 日本OSS推進フォーラム 第2回 若手技術者勉強会 (2012年9月28日実施)のために作成されました。

ここでは、Linuxサーバーを1人1台使用して、異なる特性を持つ2つの分散 型NOSQL製品と性能測定ツールを試します。

NOSQL製品

性能測定ツール

また、自習用に別冊としてHBaseのハンズオン手順も用意します。 ( 後日公開予定

NOSQL製品

性能測定ツール

1-1. ハンズオンの目的

ハンズオンを終えると以下のことができるようになります。

2. 環境のセットアップ

9月28日のハンズオン環境は、仮想サーバーのディスクイメージとして用意さ れています。仮想サーバーの起動は勉強会運営メンバーの指示に従ってくださ い。

また自習のために、今回の環境を1から設定するための手順も用意します。 ( 後日公開予定

目次

2-1. 仮想サーバーにsshでログイン

PuTTYを立ち上げ、sshで接続します。

2-2. パスワードの変更

ログインに成功したら、パスワードを変更してください。これにより、他の受 講生があなたのサーバーに誤ってログインしてしまうことを防げます。

$ passwd □
(current) UNIX password: (現在のパスワード) □
New password: (新しいパスワード) □
Retype new password: (新しいパスワードを再入力) □

2-3. ハンズオンコンテンツのアップデート

ハンズオンで使用するスクリプトなどのファイルは、仮想サーバーの 「hands-on」ディレクトリに入っています。hands-onディレクトリの内容は、 バージョン管理システムのGitで管理されています。以下のコマンドで最新版 にアップデートしてください。

$ cd ~/hands-on □
$ git pull  □
...(略)

以下のコマンドで、最後のコミット(ファイルの更新)に対するSHA-1チェッ クサムを表示します。

$ git branch -v  □
出力の例
* master 9e76bae Add how to draw the summary chart with R.

重要
チェックサムが会場の白板に書かれたものと一致することを確認してください。

2-4. 製品のバージョン

仮想サーバーにはハンズオンで使用するNOSQLと性能測定ツールがすでに導入 されています。各製品のバージョンは以下の通りです。

2-5. ディレクトリ構成

/home/
    ossforum/
        basho_bench/
        bin/
        erlang/

        hands-on/
            README.md
            bin/             ← ハンズオンで使用するスクリプトが含まれている
            conf-bb/           ← Basho Benchのワークロード設定ファイル
            docs/
                hands-on.txt
                hands-on.html  ← このドキュメント
            lib/

        hibari/
        riak/
        riak-client-erlang/

2-6. PuTTYのごく基本的な操作

コピー&ペースト

他のアプリでコピーしたテキストをPuTTYにペーストする(貼り付ける)には、 マウスの右ボタンをクリックします。

PuTTYのウィンドウに表示されたテキストをコピーするには、コピーしたい 範囲をマウスで選択します。(選択するだけでクリップボードにコピーされ ます。

2-7. Linuxシェルのごく基本的な操作

Linuxシェルの履歴検索やコマンド補完

上矢印(↑)キーを押すと以前入力したコマンドを呼び出せます。また Control キーと r キーを同時に押すとコマンドの入力履歴を検索できま す。さらに、コマンドの入力途中で Tab キーを押すと、残りの部分が補完 されます。

Linuxシェルでテキストファイルの内容を表示、編集する

スクリプトのようなテキストファイルの内容を表示するには、 less コマン ドを使用します。また、テキストファイルの内容を編集するには、 nano コ マンド(または vi、emacs)を使用します。ファイルの編集が終わったら、 Control キーと x キーを同時に押して保存します。

3. Basho Riakの基本操作

目次

Riakの特徴

Riakの起動とクラスター構成の確認

今回は学習のために、1台のLinux仮想サーバー上で複数のRiakメンバーノー ドを動かします。

3-1. Riakの起動

今回用意したスクリプトを使ってRiakクラスターを起動します。

# □で改行キーを押します

$ riak-start-ossforum.sh □

riak1 started
riak2 started
...(略)


# 起動後の確認。pongと帰ってくればOK

$ riak-ping-ossforum.sh □

riak1 ... pong
riak2 ... pong
...(略)
3-2. クラスター構成の確認

このRiakクラスターには、いくつの メンバーノード がありますか? 以下 のコマンドで調べましょう。

コマンド
$ riak-admin member-status □
サンプル出力
 ================================= Membership ==================================
 Status     Ring    Pending    Node
 -------------------------------------------------------------------------------
 valid      50.0%      --      'riak1@127.0.0.1'
 valid      50.0%      --      'riak2@127.0.0.1'
 -------------------------------------------------------------------------------
 Valid:2 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

「Node」の欄を見ると、この例では「riak1」と「riak2」の2個のメンバーノー ドがあることがわかります。(ハンズオン用の構成はこの例とは異なります)

RiakのクライアントAPI

Riakには3種類のクライアントAPIが用意されています。

今回はプログラミング言語にはErlangを使用し、Protocol Buffersで接続しま す。他の言語でも基本的な操作方法は同じですので、後日、お気に入りの言語 で試してみてもいいでしょう。

Riakのデータモデル

Protocol Buffersでアクセス(Erlang)

3-3. バケットの作成

最初にバケットを作りましょう。バケットは一般的なデータベースのテーブル にあたります。

$ riak-create-buckets-ossforum.escript □

Created {<<"employee">>,{n_val,3},{r,quorum},{w,quorum},{dw,quorum}}
Created {<<"basho_bench_test">>,{n_val,3},{r,quorum},{w,quorum},{dw,quorum}}

2つのバケットが作られました。

3-4. Riakに接続

RiakへProtocol Buffersで接続しましょう。

まず、Erlangのシェルを立ち上げます。

$ erl-riak-ossforum.sh □

Erlang R15B02 (erts-5.9.2) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.2  (abort with ^G)
1>

Erlangシェルのプロンプト「1>」は、以下、「>」で示します。

次に、Riakに接続します。

> {ok, Conn} = riakc_pb_socket:start("127.0.0.1", 8091). □
{ok,<0.33.0>}

デフォルトのポート番号は8087ですが、今回は1台の仮想サーバーに複数のメ ンバーノードを稼働させるために設定を変更してあります。

  • 各メンバーノードのProtocol Buffersポート

    • riak1: 8091

    • riak2: 8092

    • riak3: 8093

Erlangシェルの便利な使い方

Erlangでエラーが出て動かない時の対応

exception exit … gen_sever,call
> riakc_pb_socket:put(Conn, Je).
** exception exit: {noproc,
                       {gen_server,call,
                           [<0.34.0>,
                            {req,
                                {rpbputreq,<<"employee">>,<<"jeremy">>,undefined,
                                    {rpbcontent,<<"engineer">>,undefined,undefined,
                                        undefined,undefined,[],undefined,undefined,[],[],
                                        undefined},
                                    undefined,undefined,undefined,undefined,undefined,
                                    undefined,undefined},
                                60000},
                            infinity]}}
     in function  gen_server:call/3 (gen_server.erl, line 188)

*原因*

何らかの理由でRiakクライアントが停止した時に起こります。

対処法

Riakに接続しなおします。

%% Conn変数をリセットします
> f(Conn).

%% Riakに再接続します
> {ok, Conn} = riakc_pb_socket:start("127.0.0.1", 8091).
exception error: no match of right hand side value
> Je = riakc_obj:new(<<"employee">>, <<"jeremy">>, <<"engineer">>).
** exception error: no match of right hand side value
                    {riakc_obj,<<"employee">>,<<"jeremy">>,undefined,[],
                               undefined,<<"engineer">>}

*原因*

値を設定済みの変数に、違う値を再度設定しようとしたため。 (Erlangでは変数への値の設定は1回だけに制限されています)

対処法

まず、「=」記号の左側にある変数名(例「Je」)が間違っていないことを 確認してください。

間違っていなら、f() コマンドを使って変数をリセットします。 (f は forget の略です)

%% 例:変数「Je」をリセットします
> f(Je).
3-5. キー・バリューを格納

「employee(社員)」というバケットに、1つ目のキー・バリューを格納しま しょう。

  • キー:   jeremy

  • バリュー: engineer

%% キー・バリューを作成
> Je = riakc_obj:new(<<"employee">>, <<"jeremy">>, <<"engineer">>). □
{riakc_obj,<<"employee">>,<<"jeremy">>,undefined,[],
           undefined,<<"engineer">>}


%% Riakに書き込み
> riakc_pb_socket:put(Conn, Je). □
ok
3-6. キーを指定してキー・バリューを取り出し

キーを指定してキー・バリューを取り出します。

> riakc_pb_socket:get(Conn, <<"employee">>, <<"jeremy">>). □
{ok,{riakc_obj,<<"employee">>,<<"jeremy">>,
               <<107,206,97,96,96,96,204,96,202,5,82,28,7,47,197,115,6,
                 36,181,50,100,48,37,...>>,
               [{{dict,2,16,16,8,80,48,
                       {[],[],[],[],[],[],[],[],[],[],[],[],...},
                       {{[],[],[],[],[],[],[],[],[],[],...}}},
                 <<"engineer">>}],
               undefined,undefined}}


%% キーが存在しないときは「notfound」になります。
> riakc_pb_socket:get(Conn, <<"employee">>, <<"gary">>). □
{error,notfound}
3-7. インデックス付きの、キー・バリューを格納

後で検索できるよう、インデックス(索引)に「age_int(年齢、整数型)」 と「state_bin(居住している州、バイナリー型)」を登録します。

先ほど作成したキー・バリューに索引情報を追加しましょう。

%% Riakからキー・バリューを取り出します。
> {ok, Je1} = riakc_pb_socket:get(Conn, <<"employee">>, <<"jeremy">>). □
{ok,{riakc_obj,<<"employee">>,<<"jeremy">>,
               <<107,206,97,96,96,96,204,96,202,5,82,28,7,47,197,115,6,
                 36,181,50,100,48,37,...>>,
               [{{dict,2,16,16,8,80,48,
                       {[],[],[],[],[],[],[],[],[],[],[],[],...},
                       {{[],[],[],[],[],[],[],[],[],[],...}}},
                 <<"engineer">>}],
               undefined,undefined}}


%% キー・バリューに付いているメタデータを取り出します。
> JeM1 = riakc_obj:get_metadata(Je1). □
{dict,2,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],[],[],[],[],[],[],[],[],[],
        [[<<"X-Riak-VTag">>,49,55,99,104,99,105|...]],
        [],[],
        [[<<"X-Riak-Last-"...>>|{1348,634022,...}]],
        [],[]}}}


%% メタデータにインデックス情報を追加します。
%% age_intは年齢を整数型で表したもの。
%% state_binは居住している州をバイナリー型で表したもの。
> JeM2 = dict:store(<<"index">>, [{"age_int", "23"}, {"state_bin", "CA"}], JeM1). □
{dict,3,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],[],[],[],[],[],[],[],[],[],
        [[<<"X-Riak-VTag">>,49,55,99,104,99,105|...]],
        [[<<"index">>,{"age_int","23"},{"state_bin","CA"}]],
        [],
        [[<<"X-Riak-Last-"...>>|{1348,634022,...}]],
        [],[]}}}

%% キー・バリューのメタデータを新しいものに置き換えます。
> Je2 = riakc_obj:update_metadata(Je1, JeM2). □
{riakc_obj,<<"employee">>,<<"jeremy">>,
           <<107,206,97,96,96,96,204,96,202,5,82,28,7,47,197,115,6,
             36,181,50,100,48,37,50,230,...>>,
           [{{dict,2,16,16,8,80,48,
                   {[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                   {{[],[],[],[],[],[],[],[],[],[],[[...]],[],...}}},
             <<"engineer">>}],
           {dict,3,16,16,8,80,48,
                 {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                 {{[],[],[],[],[],[],[],[],[],[],
                   [[<<...>>|...]],
                   [[...]],
                   [],...}}},
           undefined}

%% Riakに書き込みます(Je2の方を書き込みます)
> riakc_pb_socket:put(Conn, Je2). □
ok

2つ目のキー・バリューを格納します。

> He1 = riakc_obj:new(<<"employee">>, <<"helena">>, <<"scientist">>). □
{riakc_obj,<<"employee">>,<<"helena">>,undefined,[],
           undefined,<<"scientist">>}

> HeM1 = dict:store(<<"index">>, [{"age_int", "29"}, {"state_bin", "CA"}], dict:new()). □
{dict,1,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],[],[],[],[],[],[],[],[],[],[],
        [[<<"index">>,{"age_int","29"},{"state_bin","CA"}]],
        [],[],[],[]}}}

> He2 = riakc_obj:update_metadata(He1, HeM1). □
{riakc_obj,<<"employee">>,<<"helena">>,undefined,[],
           {dict,1,16,16,8,80,48,
                 {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],...},
                 {{[],[],[],[],[],[],[],[],[],[],[],[[...]],[],...}}},
           <<"scientist">>}

> riakc_pb_socket:put(Conn, He2). □
ok
3-8. インデックスを用いた検索

インデックス情報を用いてキー・バリューを検索しましょう。 get_index では指定した条件に合致するキー・バリューを見つけて、一連のキーを返しま す。

%% employeeバケットの中で、state_binが「CA」のもの
> riakc_pb_socket:get_index(Conn, <<"employee">>, "state_bin", "CA"). □
{ok,[<<"jeremy">>,<<"helena">>]}

%% employeeバケットの中で、state_binが「NY」のもの
%% 該当するキー・バリューがない場合は、空のリストが返されます
> riakc_pb_socket:get_index(Conn, <<"employee">>, "state_bin", "NY"). □
{ok,[]}

%% employeeバケットの中で、age_intが「23」のもの
> riakc_pb_socket:get_index(Conn, <<"employee">>, "age_int", "23"). □
{ok,[<<"jeremy">>]}

%% employeeバケットの中で、age_intが「20」以上、「29」以下のもの
> riakc_pb_socket:get_index(Conn, <<"employee">>, "age_int", "20", "29"). □
{ok,[<<"helena">>,<<"jeremy">>]}
3-9. キー・バリューの削除

キー・バリューを削除しましょう。

> riakc_pb_socket:delete(Conn, <<"employee">>, <<"jeremy">>). □
ok

> riakc_pb_socket:delete(Conn, <<"employee">>, <<"helena">>). □
ok

Riakでは存在しないキー・バリューに対する削除もエラーになりません。 (その理由は整合性重視のHibariを試した後に説明します)

%% キー・バリューが存在しない時もエラーになりません!
> riakc_pb_socket:delete(Conn, <<"employee">>, <<"gary">>).
ok
3-10. Erlangシェルの終了

q()コマンド(quitコマンド)でErlangシェルを終了します。

> q().
ok
>
$

4. データ分散について:コンシステント・ハッシング

Riakを用いてコンシステント・ハッシングの基本を確認します。

目次

Riakのリング

http://wiki.basho.com/What-is-Riak%3F.html

リング関連の操作

4-1. リングサイズの確認

このRiakクラスターのリングを確認しましょう。今回、Ringの情報をRiakクラ スターに問い合わせるスクリプトを用意しました。

$ riak-ring-ossforum.escript □
結果の例
Ring Size: 8

[{1,0,'riak1@127.0.0.1'},
 {2,182687704666362864775460604089535377456991567872,'riak2@127.0.0.1'},
 {3,365375409332725729550921208179070754913983135744,'riak3@127.0.0.1'},
 {4,548063113999088594326381812268606132370974703616,'riak1@127.0.0.1'},
 {5,730750818665451459101842416358141509827966271488,'riak1@127.0.0.1'},
 {6,913438523331814323877303020447676887284957839360,'riak2@127.0.0.1'},
 {7,1096126227998177188652763624537212264741949407232,'riak3@127.0.0.1'},
 {8,1278813932664540053428224228626747642198940975104,'riak1@127.0.0.1'}]

それぞれの行をRiakでは「仮想ノード(vnode)」と呼びます。 左側の数字が仮想ノードの番号、真ん中がハッシュ値、右側の名前がRiakのメ ンバーノード名です。

「Ring Size」の欄にリングの大きさ(仮想ノードの数)が表示されています。 仮想ノードはいくつありますか?

4-2. バケット名とキーからハッシュ値を算出

Riakではバケット名とキーからハッシュ値を算出します。今回、そのハッシュ 値をRiakクラスターに問い合わせるスクリプトを用意しました。

このスクリプトを使って「employee」バケットにキー「key1」を格納する際の ハッシュ値を求めてください。

$ riak-keyhash-ossforum.escript employee key1 □
employee/key1: 571163913345190032512049582966850509153338820326

「571163913345190032512049582966850509153338820326」がハッシュ値です。

同様に「employee」バケットに「key2」を格納する際のハッシュ値を求めてく ださい。

$ riak-keyhash-ossforum.escript employee key2 □
...(略)

この2つのキーはとてもよく似ています。生成された2つのハッシュ値は似て いますか?

4-3. キーを格納するノードを算出

データがどのノードに格納されるか調べましょう。今回、以下のスクリプトを 用意しました。

$ riak-preflist-ossforum.escript employee key1 □
結果の例
employee/key1: 571163913345190032512049582966850509153338820326

Primaries:
[{5,730750818665451459101842416358141509827966271488,'riak1@127.0.0.1'},
 {6,913438523331814323877303020447676887284957839360,'riak2@127.0.0.1'},
 {7,1096126227998177188652763624537212264741949407232,'riak3@127.0.0.1'}]

Fallbacks:
[{8,1278813932664540053428224228626747642198940975104,'riak1@127.0.0.1'},
 {1,0,'riak1@127.0.0.1'},
 {2,182687704666362864775460604089535377456991567872,'riak2@127.0.0.1'},
 {3,365375409332725729550921208179070754913983135744,'riak3@127.0.0.1'},
 {4,548063113999088594326381812268606132370974703616,'riak1@127.0.0.1'}]

クラスターが健全な時は、キー・バリューはPrimariesの3つの仮想ノードに 格納されます。Primariesのどの仮想ノードが使われるかは、キーのハッシュ値で 決まります。この例では、キーのハッシュ値と各仮想ノードのハッシュ値が以下の 関係にあります。

  • 仮想ノード4のハッシュ値 < キーのハッシュ値 ≦ 仮想ノード5のハッシュ値

この場合、キー・バリューの1つ目の複製は、仮想ノード5に格納されます。 このバケットでは複製数が3に設定されていますので、キー・バリューの他の 2つの複製が、仮想ノード6と7に格納されます。

Primariesの仮想ノードに何か問題がある時は、Fallbacksにある仮想ノードが、 上から順番に使われます。

では「key1」と同様に、「key2」が格納されるノードも調べて下さい。

$ riak-preflist-ossforum.escript employee key2 □

注意:メンバーノードには「riakN@127.0.0.1 」のような名前がついています。 (Nは数字) riakNの形で答えてください。

4-4. 2つ以上の複製が1つのメンバーノードに格納されるケース

Riakではそれぞれの仮想ノードがメンバーノードにランダムに割り当てられま す。その結果、データの3つの複製が2つのメンバーノードにしか格納されな いことがあります。その場合、一方のメンバーノードには1つの複製が格納さ れ、もう一方のメンバーノードには2つの複製が格納されます。

キーを自由に変えて、そのようなケースが起こることを確認してください。

4-5. 2つ以上の複製を1つのメンバーノードに置かない方法

仮にあなたがRiakクラスターを自由に設計できる立場にいたとしたら、やってみよう 2-5のケースをどうやって 起こりにくく しますか? あなたは以下の要素 を決めることができます。

  • データの複製の数

  • メンバーノードの数(サーバーの台数)

  • リングのサイズ(仮想ノードの数)

  • バケットの名前やキー

4-6. メンバーノードの追加とデータのリバランス(再配置)

Riakは他の多くのNOSQLと同様に、サービスの稼働中にメンバーノードを追加 したり、取り除いたりできます。現在のクラスターにメンバーノードを追加し ましょう。

まず現在のリングの状態を確認しましょう。

$ riak-ring-ossforum.escript □

重要
この情報はリングの変更後に参照しますので、Windowsのメモ帳に保存して おいてください。

新しいノード「riak4」を起動しましょう。riak4/bin/riakコマンドを使いま す。

$ $RIAK_HOME/rel/riak4/bin/riak start □

$ $RIAK_HOME/rel/riak4/bin/riak ping □
pong

riak4/bin/riak-adminの「cluster join」コマンドを使い、既存のクラスター のメンバーノード(ここではriak1)へ参加要求を送ります。なお、参加要求 を送る先はクラスターのメンバーノードならどれでも構いません。riak2や riak3でも同じ結果になります。

$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster join riak1@127.0.0.1 □
Success: staged join request for 'riak4@127.0.0.1' to 'riak1@127.0.0.1'

参加要求がステージングされました。この時点では、まだクラスターの構成は 変更されていません。「cluster plan」コマンドを使って、現在の構成と、変 更後の構成を確認します。

$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster plan □
結果の例
 =============================== Staged Changes ================================
 Action         Nodes(s)
 -------------------------------------------------------------------------------
 join           'riak4@127.0.0.1'
 -------------------------------------------------------------------------------


 NOTE: Applying these changes will result in 1 cluster transition

 ###############################################################################
                          After cluster transition 1/1
 ###############################################################################

 ================================= Membership ==================================
 Status     Ring    Pending    Node
 -------------------------------------------------------------------------------
 valid      50.0%     25.0%    'riak1@127.0.0.1'
 valid      25.0%     25.0%    'riak2@127.0.0.1'
 valid      25.0%     25.0%    'riak3@127.0.0.1'
 valid       0.0%     25.0%    'riak4@127.0.0.1'
 -------------------------------------------------------------------------------
 Valid:4 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

 Transfers resulting from cluster changes: 2
   2 transfers from 'riak1@127.0.0.1' to 'riak4@127.0.0.1'

「Membership」の表の「Ring」に現在の状態が、「Pending」に変更後の状態 が表示されています。

「cluster commit」コマンドで、クラスターの構成変更を実行します。

$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster commit □
Cluster changes committed

仮想ノードの分散状況を確認します。

$ riak-admin member-status □

【質問】Ringの割合は各ノードで均等になっていますか?

変更後のリングの状態を確認しましょう。メモ帳に保存した変更前の状態と見 比べてください。

$ riak-ring-ossforum.escript □

【質問】Ring上の仮想ノードの数は変わりましたか?

【質問】riak4へ移動した仮想ノードはどれですか?(複数あり)

4-7. メンバーノードの削除

今度はriak4をクラスターから取り除きましょう。

riak4/bin/riak-adminの「cluster leave」コマンドを使い、クラスターから の離脱要求を出します。

$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster leave □
Success: staged leave request for 'riak4@127.0.0.1'

メンバーノードの追加の時と同様に、構成変更の内容を確認し、実行します。

$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster plan □

 =============================== Staged Changes ================================
 Action         Nodes(s)
 -------------------------------------------------------------------------------
 leave          'riak4@127.0.0.1'
 -------------------------------------------------------------------------------

 ...(略)


$ $RIAK_HOME/rel/riak4/bin/riak-admin cluster commit □
Cluster changes committed

仮想ノードの分散状況を確認します。

$ riak-admin member-status □
...(略)

riak4が停止していることを確認します。

$ $RIAK_HOME/rel/riak4/bin/riak ping □
Node 'riak4@127.0.0.1' not responding to pings.
4-8. Riakの停止

作業が終わったらRiakを停止します。

$ riak-stop-ossforum.sh □
ok
ok
...(略)
riak2 stopped
riak1 stopped

$ riak-ping-ossforum.sh □
riak1 ... Node 'riak1@127.0.0.1' not responding to pings.
node riak1 ping failed
riak2 ... Node 'riak2@127.0.0.1' not responding to pings.
node riak2 ping failed
...(略)
Note
補足:リングのサイズについて
今回はリングについて理解しやすいよう、リングサイズを小さく設定していま す。しかし、この設定ではデータの偏りが起こりやすくなってしまいます。 Riakを業務で使用する際は、この値を大きく(数十〜数百に)設定してくださ い。

5. 可用性重視(AP)のNOSQLの挙動

Riakを使用して可用性重視(AP型)のNOSQLの挙動を確認しましょう。メンバー ノードを1つ停止して、読み出しと書き込みの動作を調べます。

目次

5-1. Riakの初期化

Riakの環境を初期化しましょう。この操作により今までRiakに保存したデータ は全て削除されます。

(Riakの停止。すでに停止しているのでエラーになります)
$ riak-stop-ossforum.sh □
Node 'riak1@127.0.0.1' not responding to pings.
Node 'riak2@127.0.0.1' not responding to pings.
...(略)
node riak1 stop failed
node riak2 stop failed
...(略)

(Riakのデータを全て削除します)
$ riak-reset-ossforum.sh □
deleted data on riak1
deleted data on riak2
...(略)

Riakを起動します。

$ riak-start-ossforum.sh □
riak1 started
riak2 started
...(略)

$ riak-ping-ossforum.sh □
riak1 ... pong
riak2 ... pong
...(略)

Riakクラスターを組み直します。

$ riak-build-cluster.sh □

 Success: staged join request for 'riak2@127.0.0.1' to 'riak1@127.0.0.1'
 Success: staged join request for 'riak3@127.0.0.1' to 'riak1@127.0.0.1'
 =============================== Staged Changes ================================
 Action         Nodes(s)
 -------------------------------------------------------------------------------
 join           'riak2@127.0.0.1'
 join           'riak3@127.0.0.1'
 -------------------------------------------------------------------------------


 NOTE: Applying these changes will result in 1 cluster transition

 ###############################################################################
                         After cluster transition 1/1
 ###############################################################################

 ================================= Membership ==================================
 Status     Ring    Pending    Node
 -------------------------------------------------------------------------------
 valid     100.0%     50.0%    'riak1@127.0.0.1'
 valid       0.0%     25.0%    'riak2@127.0.0.1'
 valid       0.0%     25.0%    'riak3@127.0.0.1'
 -------------------------------------------------------------------------------
 Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

 WARNING: Not all replicas will be on distinct nodes

 Transfers resulting from cluster changes: 4
   2 transfers from 'riak1@127.0.0.1' to 'riak3@127.0.0.1'
   2 transfers from 'riak1@127.0.0.1' to 'riak2@127.0.0.1'

 Cluster changes committed
 ================================= Membership ==================================
 Status     Ring    Pending    Node
 -------------------------------------------------------------------------------
 valid      50.0%      --      'riak1@127.0.0.1'
 valid      25.0%      --      'riak2@127.0.0.1'
 valid      25.0%      --      'riak3@127.0.0.1'
 -------------------------------------------------------------------------------
 Valid:3 / Leaving:0 / Exiting:0 / Joining:0 / Down:0

バケットを作成します。

$ riak-create-buckets-ossforum.escript □
Created {<<"employee">>,{n_val,3},{r,quorum},{w,quorum},{dw,quorum}}
Created {<<"basho_bench_test">>,{n_val,3},{r,quorum},{w,quorum},{dw,quorum}}
5-2. 1ノードダウン時の読み出し操作

メンバーノードの1つが停止しているときの読み出しの挙動を確認しましょう。 まず、全ノードが稼働している状態で書き込みを行い、次に、メンバーノード の1つを停止します。

sshターミナルのウィンドウを2つ開いてください。一方はErlangシェル、も う一方はLinuxシェル(bash)を動かしましょう。

2つのウィンドウを開いたら、以下のコマンドを実行します。

Erlangシェル用ウィンドウ
$ erl-riak-ossforum.sh □

> {ok, Conn} = riakc_pb_socket:start("127.0.0.1", 8091).> Ann = riakc_obj:new(<<"employee">>, <<"ann">>, <<"disigner">>).%% W = allで書き込みます
> riakc_pb_socket:put(Conn, Ann, [{w, all}]).

オブジェクトを書き込んだらメンバーノードの1つを停止しましょう。まず キー・バリューがどのノードに書き込まれたか調べます。

bash用ウィンドウ
$ riak-preflist-ossforum.escript employee ann □
Targets:
[{1096126227998177188652763624537212264741949407232,'riak3@127.0.0.1'},
 {1278813932664540053428224228626747642198940975104,'riak1@127.0.0.1'},
 {0,'riak1@127.0.0.1'}]
...(略)

該当するメンバーノードを停止します。ただしriak1を停止することは避けて ください(本環境ではriak1を使ってriak-adminコマンドを動かしているため、 riak1を停止するとriak-adminコマンドが使えなくなります)

bash用ウィンドウ
(例:riak3を止める場合)
$ $RIAK_HOME/rel/riak3/bin/riak stop □
$ $RIAK_HOME/rel/riak3/bin/riak ping □
Node 'riak3@127.0.0.1' not responding to pings.


%% Ringステータスを確認します。

$ riak-admin ring-status □
================================== Claimant ===================================
Claimant:  'riak1@127.0.0.1'
Status:     up
Ring Ready: true

============================== Ownership Handoff ==============================
No pending changes.

============================== Unreachable Nodes ==============================
The following nodes are unreachable: ['riak3@127.0.0.1']

WARNING: The cluster state will not converge until all nodes
...(略)

「Unreachable Nodes」(音信不通のノード)に停止したノード(例: riak3)が表示されることを確認します。

R = allで読み出しを試みます。

Erlangシェル用ウィンドウ
> riakc_pb_socket:get(Conn, <<"employee">>, <<"ann">>, [{r, all}]).
...(略)

もう一度、R = allで読み出しを試みます。

Erlangシェル用ウィンドウ
> riakc_pb_socket:get(Conn, <<"employee">>, <<"ann">>, [{r, all}]).
...(略)

2回の読み出しは成功しましたか?

5-3. 1ノードダウン時の書き込み操作

メンバーノードの1つが停止したまま書き込みの挙動を確認しましょう。

W = allで書き込みを試みます。

Erlangシェル用ウィンドウ
> Bob = riakc_obj:new(<<"employee">>, <<"bob">>, <<"sales">>).%% W = allで書き込みます
> riakc_pb_socket:put(Conn, Bob, [{w, all}])....(略)

書き込みは成功しましたか?

Note
Cassandraでの書き込み
CassandraではW = allの時に書き込みが失敗します。
5-4. Riakの停止

作業が終わったらRiakを停止します。

$ riak-stop-ossforum.sh □
ok
ok
...(略)
riak2 stopped
riak1 stopped

$ riak-ping-ossforum.sh □
riak1 ... Node 'riak1@127.0.0.1' not responding to pings.
node riak1 ping failed
riak2 ... Node 'riak2@127.0.0.1' not responding to pings.
node riak2 ping failed
...(略)

6. Hibariの基本操作

目次

Hibari(雲雀)の特徴

Hibariのデータモデル

Hibariの起動とクラスター構成の確認

今回は学習のために、1台のLinux仮想サーバー上で複数のHibariメンバーノー ド(「ブリックサーバー」と呼びます)を動かします。

チェイン・レプリケーションの解説 http://hibari.github.com/hibari-doc/hibari-tutorial.en.html#_hibari_chain_replication

6-1. Hibariの起動

今回用意したスクリプトを使ってHibariクラスターを起動します。

$ hibari-start-ossforum.sh □
hibari1 started
hibari2 started
...(略)

$ hibari-ping-ossforum.sh □
hibari1 ... pong
hibari2 ... pong
...(略)
6-2. テーブルの作成
$ hibari-create-tables-ossforum.sh □
ok
ok
Table employee created
ok
Table basho_bench_test_simple created
ok
Table basho_bench_test_sequential created
ok
Table basho_bench_test_random created

このスクリプトにより4つのテーブルが作られました。

6-3. クラスター構成の確認

このHibariクラスターには、いくつの ブリックサーバー が使われていますか?  Web UIで調べてください。

ページの下の方にある「Nodes」と書かれた表を見ます。

6-4. チェインの確認

このHibariクラスターのテーブル「 basho_bench_test_simple 」には、何 本の チェイン がありますか? Web UIで調べてください。

Chainsの表の「Name」の欄を見てください。「basho_bench_test_simple_ch1」 の「…_ch1」を見ると、1からいくつまでありますか?

HibariのクライアントAPI

Hibariでは3種類のクライアントAPIが用意されています。

今回はErlangネイティブクライアントを使用します。

Erlangネイティブクライアントでアクセス

6-5. Hibariに接続
$ erl-hibari-ossforum.sh □

Erlang R15B02 (erts-5.9.2) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.2  (abort with ^G)
(hibari_client@127.0.0.1)1>

以下、プロンプト「(hibari_client@127.0.0.1)1>」は「>」で示します。

6-6. キーバリューの書き込み
Hibariに接続
> AdminNode = 'hibari1@127.0.0.1'.'hibari1@127.0.0.1'

> hibari_client_utils:connect(AdminNode)....(略:大量のログが出力されますが、最後にokと表示されれば大丈夫です)
ok.

%% employeeテーブルについて、コンシステント・ハッシング情報とノードの
%% 稼働状況を取得します。

> hibari_client_utils:wait_for_tables(AdminNode, [employee]). □
ok.
キーバリューをHibariに格納
%% テーブル:employee、キー:jeremy/title、バリュー:"engineer"
> brick_simple:set(employee, "jeremy/title", "engineer"). □
ok

%% テーブル:employee、キー:jeremy/age、バリュー:23(符号なし8ビット整数)
> brick_simple:set(employee, "jeremy/age", <<23:8/unsigned-little-integer>>). □
ok

%% テーブル:employee、キー:jeremy/age、バリュー:"CA"
> brick_simple:set(employee, "jeremy/state", "CA"). □
ok
6-7. キー・バリューの読み出し
> brick_simple:get(employee, "jeremy/title"). □
{ok,1348744080833154,<<"engineer">>}


%% キー・バリューが存在しないときは、key_not_existが返されます
> brick_simple:get(employee, "gary/title"). □
key_not_exist
6-8. フラグ付きのキー・バリューを書き込み

キー・バリューにフラグ(メタデータ)をつけることができます。

%% value_in_ram でバリューをメモリー上に常駐させる
> brick_simple:set(employee, "jeremy/login-counter", <<0:64/unsigned-integer>>, [value_in_ram]). □
ok.

%% ユーザー定義フラグも格納できます
> brick_simple:set(employee, "ann/title", "designer", [{activities, "yoga"}]). □
ok.

%% バリューと同時にユーザー定義フラグ読み出し
> brick_simple:get(employee, "ann/title", [get_all_attribs]). □
{ok,1348744156095280,<<"designer">>,0,
    [{val_len,8},{activities,"yoga"}]}

%% ユーザー定義フラグのみを読み出し(ディスクアクセスを伴わないので高速)
> brick_simple:get(employee, "ann/title", [witness, get_all_attribs]). □
{ok,1348744156095280,[{val_len,8},{activities,"yoga"}]}
6-9. 複数のキー・バリューをまとめて書き込み

doを使うと同一テーブルの同一チェインに対する操作を一度に実行でいます。

> Ops1 = [brick_server:make_set("helena/title", "scientist"),
          brick_server:make_set("helena/age",   <<29:8/unsigned-little-integer>>),
          brick_server:make_set("helena/state", "CA")]. □

[{set,<<"helena/title">>,1348744219017408,"scientist",0,[]},
 {set,<<"helena/age">>,1348744219017422,<<29>>,0,[]},
 {set,<<"helena/state">>,1348744219017425,"CA",0,[]}]


> brick_simple:do(employee, Ops1). □
[ok,ok,ok]
6-10. キーの区切り文字とレンジスキャン

employee テーブルではキーの区切り文字として「/」が使われています。

%% binary_prefixを指定することで、キーがhelenaで始まるものだけを読み出します。
%% キーは辞書順にソートされて格納されています。

> brick_simple:get_many(employee, "helena", 10, [{'binary_prefix', <<"helena">>}]). □
{ok,{[{<<"helena/age">>,1348744219017422,<<29>>,0,
       [{val_len,1}]},
      {<<"helena/state">>,1348744219017425,<<"CA">>,0,
       [{val_len,2}]},
      {<<"helena/title">>,1348744219017408,<<"scientist">>,0,
       [{val_len,9}]}],
     false}}


%% キーだけを取り出すこともできます。Hibariではキーとメタデータはメモ
%% リー上に常駐していますので、ディスクアクセスなしで結果を得られます。

> brick_simple:get_many(employee, "helena", 10, [witness, {'binary_prefix', <<"helena">>}]). □
{ok,{[{<<"helena/age">>,1348744219017422},
      {<<"helena/state">>,1348744219017425},
      {<<"helena/title">>,1348744219017408}],
     false}}
6-11. キー・バリューの削除

> brick_simple:delete(employee, "jeremy/title").%% キーが存在しない時はエラーになります
> brick_simple:delete(employee, "gary/titse"). □
key_not_exist
6-12. Erlangシェルの終了

q()コマンド(quitコマンド)でErlangシェルを終了します。

> q().
ok
>
$

7. 整合性重視(CP)のNOSQLの挙動

Hibariを使用して整合性重視(CP型)のNOSQLの挙動を確認しましょう。ブリッ クサーバーを1つ停止して、読み出しと書き込みの動作を調べます。

目次

7-1. 1ノードダウン時の読み出し操作

ブリックサーバーの1つが停止しているときの読み出しの挙動を確認しましょ う。まず、全ノードが稼働している状態で書き込みを行い、次に、ブリックサー バーの1つを停止します。

sshターミナルのウィンドウを2つ開いてください。一方はErlangシェル、も う一方はLinuxシェル(bash)を動かしましょう。

2つのウィンドウを開いたら、以下のコマンドを実行します。

Erlangシェル用ウィンドウ
$ erl-hibari-ossforum.sh □
> AdminNode = 'hibari1@127.0.0.1'.'hibari1@127.0.0.1'

> hibari_client_utils:connect(AdminNode)....
ok

> hibari_client_utils:wait_for_tables(AdminNode, [employee]). □
ok

%% キーバリューをHibariに格納

> brick_simple:set(employee, "ann/title", "designer"). □
ok

ブリックサーバーの1つを停止します。

bash用ウィンドウ
$ $HIBARI_HOME/rel/hibari3/bin/hibari stop □
ok

$ $HIBARI_HOME/rel/hibari3/bin/hibari ping □
Node 'hibari3@127.0.0.1' not responding to pings.

Web UIでチェインの状態を確認します。

「Bricks」の表の「employee_ch」(チェイン)の状態を見て、「degraded」 (縮退運行中)であることを確認します。

読み出を試みます。もし読み出しに失敗した場合は「brick_not_available」 が返されます。なおHibariでは読み出しはR=1に固定されています。

Erlangシェル用ウィンドウ
> brick_simple:get(employee, "ann/title").

読み出しは成功しましたか?

7-2. 1ノードダウン時の書き込み操作

ブリックサーバーの1つが停止したまま書き込みの挙動を確認しましょう。

書き込みを試みます。もし書き込みに失敗した場合は「brick_not_available」 が返されます。

Erlangシェル用ウィンドウ
> brick_simple:set(employee, "bob/title", "sales").

書き込みは成功しましたか?

8. 整合性重視(CP)のNOSQLだけで実現可能な操作

整合性重視(CP)のNOSQLだけで可能となる操作を紹介しましょう。

これらの操作は、キー・バリューの全ての複製で整合性がとれていないと実現 できません。可用性重視(AP)のNOSQLでは、ネットワーク分断時に複製間の 不整合を許すため実現不可能です。

目次

8-1. キー・バリューの存在チェック

キー・バリューの追加、更新、削除の際に、キー・バリューの存在チェックが できます。

一見、できて当たり前と思える機能ですが、キー・バリューの全ての複製の整 合性している必要があるため、整合性重視のNOSQLだけで実現できます。

%% caren/titleを新規に登録
> brick_simple:add(employee, "caren/title", "engineer"). □
ok

%% 再び登録しようとすると失敗します。
> brick_simple:add(employee, "caren/title", "designer"). □
{key_exists,1348744725037912}

%% 既存のキー・バリューを置き換え。
> brick_simple:replace(employee, "caren/title", "designer"). □
ok

%% キー・バリューが存在しないときは失敗します。
> brick_simple:replace(employee, "mike/title", "disigner"). □
key_not_exist

6-11で確認したように、キー・バリューが存在しない時の削除(delete)操作 もエラーになります。一方、Riakでは3-9で確認したように、エラーになりま せん。

8-2. CAS操作

CAS操作(Check And Swap)を使うと、複数クライアントの同時更新を制御で きます。キー・バリューの全ての複製が同期している必要があるため、整合性 重視のNOSQLだけで実現できます。

%% クライアント1がログインカウンターを読み出し
%% Ts1にはキー・バリューが最後に更新された時刻が入る
> {ok, Ts1, <<Val1:64/unsigned-integer>>} = brick_simple:get(employee, "jeremy/login-counter"). □
{ok,1348744147878810,<<0,0,0,0,0,0,0,0>>}


%% その直後、クライアント2がログインカウンターを読み出したと想定しましょう。
{ok, Ts2, <<Val2:64/unsigned-integer>>} = brick_simple:get(employee, "jeremy/login-counter"). □
{ok,1348744147878810,<<0,0,0,0,0,0,0,0>>}


%% クライアント2が先にカウンターを更新しました。
%% testsetでタイムスタンプを確認し、以前と変わってなければ更新します。
> brick_simple:set(employee, "jeremy/login-counter", <<(Val2 + 1):64/unsigned-integer>>,
                   [value_in_ram, {testset, Ts2}]). □
ok

%% クライアント1がカウンターを更新しようとしても
%% タイムスタンプが変わっているので失敗します。
> brick_simple:set(employee, "jeremy/login-counter", <<(Val1 + 1):64/unsigned-integer>>,
                   [value_in_ram, {testset, Ts1}]). □
{ts_error,1348744830713999}
8-3. Hibariのマイクロトランザクション

Hibariでは同一テーブルの同一チェイン上なら、複数のキー・バリューをアト ミックに追加できます。この場合は、すべての操作が成功するか、あるいは、 すべての操作が実行されないか、のどちらかになります。

Hibariだけで実現されている機能です。

%% helenaさんの情報はすでに登録済みです。
> brick_simple:get(employee, "helena/title"). □
{ok,1348744219017408,<<"scientist">>}

%% 同じキーで別人を登録しようとするとどうなるでしょうか?
%% 一連の操作をトランザクションとして実行します。
> Ops2 = [brick_server:make_txn(),
          brick_server:make_add("helena/title",    "sales"),
          brick_server:make_set("helena/state",    "NY"),
          brick_server:make_set("helena/lastname", "smith")]. □

[txn,
 {add,<<"helena/title">>,1348745055483211,"sales",0,[]},
 {set,<<"helena/state">>,1348745055483221,"NY",0,[]},
 {set,<<"helena/lastname">>,1348745055483226,"smith",0,[]}]


%% トランザクションを実行しようとすると、最初のaddで失敗するので、
%% トランザクション全体がロールバックします。
> brick_simple:do(employee, Ops2). □
{txn_fail,[{1,{key_exists,1348744219017408}}]}


%% 以前の情報のままです。
> brick_simple:get(employee, "helena/state"). □
{ok,1348744219017425,<<"CA">>}

> brick_simple:get(employee, "helena/lastname"). □
key_not_exist

9. 講義:データ分散について、Riak、Cassandra、Hibariを比較

データ分散についてRiakと同様にコンシステント・ハッシングを採用した CassandraやHibariの設計を比較します。それぞれに長所と短所があります。

10. 性能測定ツールの使用

Hibariと性能測定ツールのBasho Benchを用いて、データの分散状況を観察し ます。

目次

10-1. Hibariの初期化

Hibariの環境を初期化しましょう。この操作により今までHibariに保存したデー タは全て削除されます。

(Hibariの停止。すでに停止しているのでエラーになります)
$ hibari-stop-ossforum.sh □
Node 'hibari1@127.0.0.1' not responding to pings.
Node 'hibari2@127.0.0.1' not responding to pings.
...(略)
node hibari1 stop failed
node hibari2 stop failed
...(略)

(Hibariのデータを全て削除します)
$ riak-reset-ossforum.sh □
deleted data on hibari1
deleted data on hibari2
...(略)

Hibariを起動します。

$ hibari-start-ossforum.sh □
hibari1 started
hibari2 started
...(略)

$ hibari-ping-ossforum.sh □
hibari1 ... pong
hibari2 ... pong
...(略)

テーブルを再作成します。

$ hibari-create-tables-ossforum.sh □
$ hibari-create-tables-ossforum.sh □
ok
ok
Table basho_bench_test_simple created
ok
Table basho_bench_test_sequential created
ok
Table basho_bench_test_random created
10-2. Basho Benchの実行

Basho Benchを実行しましょう。以下のコマンドを入力します。

$ cd ~/hands-on □
$ basho_bench conf-bb/hibari-simple.config □
hh:mm:ss.sss [debug] Lager installed handler lager_console_backend into lager_event
...(省略)
hh:mm:ss.sss [info] Starting 100.0 ms/req fixed rate worker: < ... >
hh:mm:ss.sss [info] Starting 100.0 ms/req fixed rate worker: < ... >
hh:mm:ss.sss [info] Starting 100.0 ms/req fixed rate worker: < ... >
...(省略)
hh:mm:ss.sss [info] Application basho_bench started on node 'basho_bench@127.0.0.1'
...(省略)

...(1分後)
hh:mm:ss.sss [info] Total Errors:
hh:mm:ss.sss [info]   {{put,put},{txn_fail,[{0,brick_not_available}]}}: 1
(または)
hh:mm:ss.sss [info] No Errors.

hh:mm:ss.sss [info] Application basho_bench exited with reason: stopped
hh:mm:ss.sss [info] Test completed after 1 mins.
  • 実行が終わると「Test completed」が出力されます。

  • 実行を途中でキャンセルするなら、Control + c を押し、プロンプトに 対して a を答えます。

ワークロード(負荷)の設定ファイルの内容を確認しましょう。 less コマンドで「hibari-simple.config」ファイルの内容を表示します。

$ less hibari-simple.config □

hibari-simple.configの内容(抜粋)

*TODO*

{mode, {rate, 8}}.
{duration, 15}.
{concurrent, 100}.
{key_generator, {int_to_bin, {uniform_int, 99000}}}.
{value_generator, {fixed_bin, 1000}}.
{operations, [{get,4}, {put,4}, {delete, 1}]}.
  • リクエストレートとワーカー?数の設定から、Basho Benchが生成する負荷 の大きさを、リクエスト/秒で表してください。以下の式で求められます。

    • リクエスト/秒 = ワーカー毎のリクエスト/秒 × ワーカー数

補足 Basho Benchのキー設定

Basho Benchでは以下のようなキーの分散設定ができます。

  • {sequential_int, MaxKey}

    • generates integers from 0..MaxKey in order and then stops the system. Note that each instance of this keygen is specific to a worker.

  • {partitioned_sequential_int, MaxKey}

    • worker processes. This is useful for pre-loading a large dataset.

  • {partitioned_sequential_int, StartKey, NumKeys}

    • same as partitioned_sequential_int, but starting at the defined StartKey and going up to StartKey + NumKeys.

  • {uniform_int, MaxKey}

    • selects an integer from uniform distribution of 0..MaxKey. I.e. all integers are equally probable.

  • {pareto_int, MaxKey}

    • selects an integer from a Pareto distribution, such that 20% of the available keys get selected 80% of the time. Note that the current implementation of this generator MAY yield values larger than MaxKey due to the mathematical properties of the Pareto distribution.

  • {truncated_pareto_int, MaxKey}

  • {function, Module, Function, Args}

    • specifies an external function that should return a key generator function. The worker Id will be prepended to Args when the function is called.

  • {int_to_bin, Generator}

    • takes any of the above _int generators and converts the number to a 32-bit binary. This is needed for some drivers that require a binary key.

  • {int_to_str, Generator}

    • takes any of the above _int generators and converts the number to a string. This is needed for some drivers that require a string key.

補足 Basho Benchのバリュー設定

Basho Benchでは以下のようなバリューを生成できます。

  • {fixed_bin, Size}

    • generates a random binary of Size bytes. Every binary is the same size, but varies in content.

  • {exponential_bin, MinSize, Mean}

    • generates a random binary which has an exponentially-distributed size. Most values will be approximately MinSize + Mean bytes in size, with a long-tail of larger values.

  • {uniform_bin, MinSize, MaxSize}

    • generates a random binary which has an evenly-distributed size between MinSize and MaxSize.

  • {function, Module, Function, Args}

    • specifies an external function that should return a value generator function. The worker Id will be prepended to Args when the function is called.

10-3. グラフのプロット(R言語)と結果の確認

実行結果をグラフにプロットしてみましょう。Basho_Benchには統計解析プロ グラミング言語の R言語 で書かれたスクリプトが付属していますので、そ れを利用してグラフを生成しましょう。

$ cd ~/hands-on
$ $BASHO_BENCH_HOME/priv/summary.r -i tests/current/

グラフはPNG形式の画像ファイルになります。WindowsシンクライアントのPSCP を使って、画像ファイルをダウンロードしましょう。

Windowsシンクライアントのコマンドプロンプト
$ pscp ossforum@仮想サーバーのIP:/home/ossforum/hands-on/tests/current/summary.png .
Note
Cygwin
もし、会場のWindowsシンクライアントにpscpコマンドが入っていない場合は、 Cygwinを使用してください。(方法は会場で説明します)

summary.pngがダウンロードできたら、ダブルクリックして開きます。

このグラフを見て、Hibariは書き込み(set)と読み出し(get)のどちらが得 意(高速)だと思いましたか?

RiakやCassandraの特性
10-4. Hibariの停止

作業が終わったらHibariを停止します。

$ hibari-stop-ossforum.sh □
ok
ok
...(略)
hibari2 stopped
hibari1 stopped

$ hibari-ping-ossforum.sh □
hibari1 ... Node 'hibari1@127.0.0.1' not responding to pings.
node hibari1 ping failed
hibari2 ... Node 'hibari2@127.0.0.1' not responding to pings.
node hibari2 ping failed
...(略)

$ hibari-reset-ossforum.sh □
...(略)
deleted data on hibari2
deleted data on hibari1
Note
時間が余ったら
もし時間が余ったら、Basho BenchでRiakの性能も測ってみてください。
$ basho_bench conf-bb/riak-simple.config □

11. 講義:コンシステントハッシングと自動シャーディングの優劣

付録. 参考資料

Basho Riak

Hibari