$ passwd □ (current) UNIX password: (現在のパスワード) □ New password: (新しいパスワード) □ Retype new password: (新しいパスワードを再入力) □
日本OSS推進フォーラム 若手技術者勉強会
このハンズオンは 日本OSS推進フォーラム 第2回 若手技術者勉強会 (2012年9月28日実施)のために作成されました。
ここでは、Linuxサーバーを1人1台使用して、異なる特性を持つ2つの分散 型NOSQL製品と性能測定ツールを試します。
NOSQL製品
Basho Riak
可用性重視(AP)、コンシステントハッシング
Hibari
一貫性重視(CP)、コンシステントハッシング
性能測定ツール
Basho Bench
Riak、Hibari向け
また、自習用に別冊としてHBaseのハンズオン手順も用意します。 ( 後日公開予定 )
NOSQL製品
Apache HBase
一貫性重視(CP)、自動シャーディング
性能測定ツール
Yahoo! Cloud Serving Benchmark (YCSB)
HBase向け
Cassandra、MongoDB、Redisにも対応
ハンズオンを終えると以下のことができるようになります。
NOSQLの2つの製品について、ごく基本的な操作ができる
性能測定ツールの基本操作ができる
データの分散方法について、「コンシステント・ハッシング」が説明できる
CAP定理の中で、可用性重視「AP」のものと、一貫性重視「CP」のものにつ いて、違いが説明できる
9月28日のハンズオン環境は、仮想サーバーのディスクイメージとして用意さ れています。仮想サーバーの起動は勉強会運営メンバーの指示に従ってくださ い。
また自習のために、今回の環境を1から設定するための手順も用意します。 ( 後日公開予定 )
目次
PuTTYを立ち上げ、sshで接続します。
ユーザー名: ossforum
パスワード: nosql2
ログインに成功したら、パスワードを変更してください。これにより、他の受 講生があなたのサーバーに誤ってログインしてしまうことを防げます。
$ passwd □ (current) UNIX password: (現在のパスワード) □ New password: (新しいパスワード) □ Retype new password: (新しいパスワードを再入力) □
ハンズオンで使用するスクリプトなどのファイルは、仮想サーバーの 「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.
「master」はブランチ名です。今回はmasterだけを使います。
「9e76bae」が、masterブランチに加えられた最後のコミットに対するSHA-1 チェックサム(の先頭部分)です。チェックサムはコミットの毎にユニーク な値になります。
「Add how to draw…」は、コミットの内容を説明するコメントです。
重要
チェックサムが会場の白板に書かれたものと一致することを確認してください。
仮想サーバーにはハンズオンで使用するNOSQLと性能測定ツールがすでに導入 されています。各製品のバージョンは以下の通りです。
NOSQL
Basho Riak 1.2
Hibari 0.1.9
性能測定ツール
Basho Bench 開発版(2012年9月10日版)
Erlang実行環境
Erlang/OTP — R15B02
Riak、Hibari、Basho Benchで使用
基本ソフトウェア
Linux — CentOS 5.8 64ビット版
/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/
他のアプリでコピーしたテキストをPuTTYにペーストする(貼り付ける)には、 マウスの右ボタンをクリックします。
PuTTYのウィンドウに表示されたテキストをコピーするには、コピーしたい 範囲をマウスで選択します。(選択するだけでクリップボードにコピーされ ます。
上矢印(↑)キーを押すと以前入力したコマンドを呼び出せます。また Control キーと r キーを同時に押すとコマンドの入力履歴を検索できま す。さらに、コマンドの入力途中で Tab キーを押すと、残りの部分が補完 されます。
スクリプトのようなテキストファイルの内容を表示するには、 less コマン ドを使用します。また、テキストファイルの内容を編集するには、 nano コ マンド(または vi、emacs)を使用します。ファイルの編集が終わったら、 Control キーと x キーを同時に押して保存します。
目次
コンシステント・ハッシングによるデータ分散
可用性を優先(AP)
キー・バリュー型
前回の訂正: 前回「ドキュメント型」と説明しましたが、「キー・バ リュー型」に分類するのが適切なようです
ストレージエンジンを選択可能(Bitcask、LevelDBなど)
豊富な機能
二次インデックス(ストレージエンジンがLevelDBの時のみ使用出来る)
全文検索(日本語の検索が可能かは未確認)
Map Reduce(JavaScript、Erlang)
高い安定性
今回は学習のために、1台のLinux仮想サーバー上で複数のRiakメンバーノー ドを動かします。
今回用意したスクリプトを使ってRiakクラスターを起動します。
# □で改行キーを押します $ riak-start-ossforum.sh □ riak1 started riak2 started ...(略) # 起動後の確認。pongと帰ってくればOK $ riak-ping-ossforum.sh □ riak1 ... pong riak2 ... pong ...(略)
この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には3種類のクライアントAPIが用意されています。
Protocol Buffers
Protocol BuffersはGoogle社が開発した異言語間のデータ・シリアライズフォーマット
様々なプログラミング言語からアクセスできます
Bashoによるオフィシャルなクライアント
Erlang、Java、Python、Ruby
コミュニティが開発したクライアント
C++
HTTP REST
様々なプログラミング言語からアクセスできます
curl コマンドや、ウェブブラウザーでアクセスできます
Bashoによるオフィシャルなクライアント
Erlang、Java、PHP、Python、Ruby
コミュニティが開発したクライアント
JavaScript
Erlangネイティブクライアント
Erlang専用のクライアント
Riak本体はErlangで書かれています
今回はプログラミング言語にはErlangを使用し、Protocol Buffersで接続しま す。他の言語でも基本的な操作方法は同じですので、後日、お気に入りの言語 で試してみてもいいでしょう。
バケット(バケツ)
オブジェクト
キー
バリュー
メタデータ
二次インデックス
最初にバケットを作りましょう。バケットは一般的なデータベースのテーブル にあたります。
$ 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つのバケットが作られました。
n_val はキー・バリューの複製(レプリカ)の数
`r` は読み出し時に応答が必要なノード数
`w` は書き込み時に応答が必要なノード数
`dw` は書き込み時にディスクへの書き込みまで行う必要のあるノード数
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
上矢印(↑)キーを押すと以前入力したコマンドを呼び出せます。
Control キーと r キーを同時に押すとコマンドの入力履歴を検索できます。
コマンドの入力途中で Tab キーを押すと、残りの部分が補完されます。
> 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). □
> 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).
「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
キーを指定してキー・バリューを取り出します。
> 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}
後で検索できるよう、インデックス(索引)に「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
インデックス情報を用いてキー・バリューを検索しましょう。 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">>]}
キー・バリューを削除しましょう。
> 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
q()コマンド(quitコマンド)でErlangシェルを終了します。
> q(). ok > $
Riakを用いてコンシステント・ハッシングの基本を確認します。
Ringの状態
キーとハッシュ関数
メンバーノードの追加とデータの偏り
目次
リング
仮想ノード(vnode)
物理ノード(メンバーノード)
この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」の欄にリングの大きさ(仮想ノードの数)が表示されています。 仮想ノードはいくつありますか?
Riakではバケット名とキーからハッシュ値を算出します。今回、そのハッシュ 値をRiakクラスターに問い合わせるスクリプトを用意しました。
このスクリプトを使って「employee」バケットにキー「key1」を格納する際の ハッシュ値を求めてください。
$ riak-keyhash-ossforum.escript employee key1 □ employee/key1: 571163913345190032512049582966850509153338820326
「571163913345190032512049582966850509153338820326」がハッシュ値です。
同様に「employee」バケットに「key2」を格納する際のハッシュ値を求めてく ださい。
$ riak-keyhash-ossforum.escript employee key2 □ ...(略)
この2つのキーはとてもよく似ています。生成された2つのハッシュ値は似て いますか?
データがどのノードに格納されるか調べましょう。今回、以下のスクリプトを 用意しました。
$ 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の形で答えてください。
Riakではそれぞれの仮想ノードがメンバーノードにランダムに割り当てられま す。その結果、データの3つの複製が2つのメンバーノードにしか格納されな いことがあります。その場合、一方のメンバーノードには1つの複製が格納さ れ、もう一方のメンバーノードには2つの複製が格納されます。
キーを自由に変えて、そのようなケースが起こることを確認してください。
仮にあなたがRiakクラスターを自由に設計できる立場にいたとしたら、やってみよう 2-5のケースをどうやって 起こりにくく しますか? あなたは以下の要素 を決めることができます。
データの複製の数
メンバーノードの数(サーバーの台数)
リングのサイズ(仮想ノードの数)
バケットの名前やキー
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へ移動した仮想ノードはどれですか?(複数あり)
今度は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.
作業が終わったら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を業務で使用する際は、この値を大きく(数十〜数百に)設定してくださ
い。 |
Riakを使用して可用性重視(AP型)のNOSQLの挙動を確認しましょう。メンバー ノードを1つ停止して、読み出しと書き込みの動作を調べます。
Quorum や Consistency Level
Hinted Hand-off と Read Repair
目次
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}}
メンバーノードの1つが停止しているときの読み出しの挙動を確認しましょう。 まず、全ノードが稼働している状態で書き込みを行い、次に、メンバーノード の1つを停止します。
sshターミナルのウィンドウを2つ開いてください。一方はErlangシェル、も う一方はLinuxシェル(bash)を動かしましょう。
2つのウィンドウを開いたら、以下のコマンドを実行します。
$ 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つを停止しましょう。まず キー・バリューがどのノードに書き込まれたか調べます。
$ 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コマンドが使えなくなります)
(例: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で読み出しを試みます。
> riakc_pb_socket:get(Conn, <<"employee">>, <<"ann">>, [{r, all}]). ...(略)
もう一度、R = allで読み出しを試みます。
> riakc_pb_socket:get(Conn, <<"employee">>, <<"ann">>, [{r, all}]). ...(略)
2回の読み出しは成功しましたか?
メンバーノードの1つが停止したまま書き込みの挙動を確認しましょう。
W = allで書き込みを試みます。
> Bob = riakc_obj:new(<<"employee">>, <<"bob">>, <<"sales">>). □ %% W = allで書き込みます > riakc_pb_socket:put(Conn, Bob, [{w, all}]). □ ...(略)
書き込みは成功しましたか?
Note
|
Cassandraでの書き込み CassandraではW = allの時に書き込みが失敗します。 |
作業が終わったら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 ...(略)
目次
コンシステント・ハッシングによるデータ分散
整合性を優先(CP)
チェインレプリケーションによる高速性
マイクロトランザクション、CAS操作
キー・バリュー型
軽快な動作と高い安定性
テーブル
キー・バリュー
キー
バリュー
フラグ(メタデータ)
有効期限
一部の情報をメモリー上に常駐させることで高速化を実現
キー、フラグ、有効期限はメモリー上に常駐します
バリューは value_in_ram を指定することでメモリー上に常駐させら れます。
今回は学習のために、1台のLinux仮想サーバー上で複数のHibariメンバーノー ド(「ブリックサーバー」と呼びます)を動かします。
チェイン・レプリケーションの解説 http://hibari.github.com/hibari-doc/hibari-tutorial.en.html#_hibari_chain_replication
今回用意したスクリプトを使ってHibariクラスターを起動します。
$ hibari-start-ossforum.sh □ hibari1 started hibari2 started ...(略) $ hibari-ping-ossforum.sh □ hibari1 ... pong hibari2 ... pong ...(略)
$ 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つのテーブルが作られました。
このHibariクラスターには、いくつの ブリックサーバー が使われていますか? Web UIで調べてください。
ページの下の方にある「Nodes」と書かれた表を見ます。
このHibariクラスターのテーブル「 basho_bench_test_simple 」には、何 本の チェイン がありますか? Web UIで調べてください。
Chainsの表の「Name」の欄を見てください。「basho_bench_test_simple_ch1」 の「…_ch1」を見ると、1からいくつまでありますか?
Hibariでは3種類のクライアントAPIが用意されています。
Erlangネイティブクライアント
プログラミング言語「Erlang」専用のクライアント
Hibari本体はErlangで書かれています
Thrift
様々なプログラミング言語からアクセスできる
現状、一部の機能しか利用できない
JSON-RPC
様々なプログラミング言語からアクセスできる
現状、一部の機能しか利用できない
今回はErlangネイティブクライアントを使用します。
$ 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>」は「>」で示します。
> 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.
%% テーブル: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
> brick_simple:get(employee, "jeremy/title"). □ {ok,1348744080833154,<<"engineer">>} %% キー・バリューが存在しないときは、key_not_existが返されます > brick_simple:get(employee, "gary/title"). □ key_not_exist
キー・バリューにフラグ(メタデータ)をつけることができます。
%% 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"}]}
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]
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}}
> brick_simple:delete(employee, "jeremy/title"). □ %% キーが存在しない時はエラーになります > brick_simple:delete(employee, "gary/titse"). □ key_not_exist
q()コマンド(quitコマンド)でErlangシェルを終了します。
> q(). ok > $
Hibariを使用して整合性重視(CP型)のNOSQLの挙動を確認しましょう。ブリッ クサーバーを1つ停止して、読み出しと書き込みの動作を調べます。
目次
ブリックサーバーの1つが停止しているときの読み出しの挙動を確認しましょ う。まず、全ノードが稼働している状態で書き込みを行い、次に、ブリックサー バーの1つを停止します。
sshターミナルのウィンドウを2つ開いてください。一方はErlangシェル、も う一方はLinuxシェル(bash)を動かしましょう。
2つのウィンドウを開いたら、以下のコマンドを実行します。
$ 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つを停止します。
$ $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に固定されています。
> brick_simple:get(employee, "ann/title"). □
読み出しは成功しましたか?
ブリックサーバーの1つが停止したまま書き込みの挙動を確認しましょう。
書き込みを試みます。もし書き込みに失敗した場合は「brick_not_available」 が返されます。
> brick_simple:set(employee, "bob/title", "sales"). □
書き込みは成功しましたか?
整合性重視(CP)のNOSQLだけで可能となる操作を紹介しましょう。
これらの操作は、キー・バリューの全ての複製で整合性がとれていないと実現 できません。可用性重視(AP)のNOSQLでは、ネットワーク分断時に複製間の 不整合を許すため実現不可能です。
目次
キー・バリューの追加、更新、削除の際に、キー・バリューの存在チェックが できます。
一見、できて当たり前と思える機能ですが、キー・バリューの全ての複製の整 合性している必要があるため、整合性重視の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で確認したように、エラーになりま せん。
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}
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
データ分散についてRiakと同様にコンシステント・ハッシングを採用した CassandraやHibariの設計を比較します。それぞれに長所と短所があります。
Basho Riak
2009年に最初のリリース
Amazon Dynamoの設計を参考にした
リングを仮想ノードで分割し、メンバーノードにランダムに配置
メンバーノードの追加時のリバランスが自動的に行われる
複製の配置が偏ることがある(1つのメンバーノードに2つの複製が 置かれることがある)
Apache Cassandra
2008年に最初のリリース
データ分散はAmazon Dynamoを参考にし、データモデルはGoogle Bigtable を参考にした
リングをメンバーノードで分割
メンバーノード追加時後のリバランスが面倒(仮想ノードの概念がないため)
複製の配置が偏らない
Hibari
2004年ごろから開発開始。50ノード超の商用利用を経て2010年にオープン ソース化
チェインレプリケーション論文を参考に設計
リングをチェインに分割して、メンバーノードにまたがって配置
メンバーノードの追加時に手動でチェインを設定する
複数のハッシュ区画を1つのチェインに割り当てられるため、リバラ ンスが容易にできる
複製の配置が偏らない
Hibariと性能測定ツールのBasho Benchを用いて、データの分散状況を観察し ます。
目次
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
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では以下のようなキーの分散設定ができます。
{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では以下のようなバリューを生成できます。
{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.
実行結果をグラフにプロットしてみましょう。Basho_Benchには統計解析プロ グラミング言語の R言語 で書かれたスクリプトが付属していますので、そ れを利用してグラフを生成しましょう。
$ cd ~/hands-on $ $BASHO_BENCH_HOME/priv/summary.r -i tests/current/
グラフはPNG形式の画像ファイルになります。WindowsシンクライアントのPSCP を使って、画像ファイルをダウンロードしましょう。
$ pscp ossforum@仮想サーバーのIP:/home/ossforum/hands-on/tests/current/summary.png .
Note
|
Cygwin もし、会場のWindowsシンクライアントにpscpコマンドが入っていない場合は、
Cygwinを使用してください。(方法は会場で説明します) |
summary.pngがダウンロードできたら、ダブルクリックして開きます。
このグラフを見て、Hibariは書き込み(set)と読み出し(get)のどちらが得 意(高速)だと思いましたか?
Cassandraは書き込みのほうが読み出しより高速です。
Riakは使用するストレージエンジンによって特性が異なります。
作業が終わったら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 □
データの分散(分布)の均一性
レンジスキャンの可否
Riak製品情報(日本語)
Riakドキュメント(英語)
Riak Fast Track(英語)
Hibari製品情報(日本語)
Hibari紹介スライド(日本語)
Hibariドキュメント