目次
# キー単位 オプション実装されているが、商用設定には未展開。
Erlangの主な利点は、
物理的なノード障害の場合、ブリックは自動的に役割をシフトし、それぞれのチェインはクライアントにサービスを提供し続ける。
データを再配置するきっかけ:
キー・バリュー・ストアであることから、HibariのコアデータモデルとクライアントAPIモデルは、設計においてシンプル。:
blobベースのキー・バリュー・ペア
オペレーション
Hibariは、複数のクライアント API実装をサポート:
Java, C/C++, Python, Ruby, Erlangを含む様々な言語におけるHibariクライアント・アプリケーション開発が可能
atom はリテラルで、名前を持つ定数。atomは、小文字で開始する場合や、アルファベット、数値、アンダースコア (_), や @以外の文字を含む場合には、シングル・クォート (') で囲まれるべき。
hello phone_number 'Monday' 'phone number' 'hello' 'phone_number'
bit string は、非型式メモリーの領域を格納するために使われる。8で割り切れるビットからなるbit string は、 binary と呼ばれる。
<<10,20>> <<"ABC">>
tuple は、中括弧で囲まれる固定数をもつ複合データ型式。:
{Term1,...,TermN}
list は、鍵括弧で囲まれる変数をもつ複合データ型式。:
[Term1,...,TermN]
true
とfalse
がBoolean values を表示するために使われる。
_… 数点追加_
ファイル "math.erl" は次のプログラムを含む。:
-module(math). -export([fac/1]). fac(N) when N > 0 -> N * fac(N-1); fac(0) -> 1.
このプログラムは、Erlang shellを使いながらコンパイルされ動作する。
$ erl Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.8.2 (abort with ^G) 1> c(math). {ok,math} 2> math:fac(25). 15511210043330985984000000
強制終了させる …
3> math:fac(-1). ** exception error: no function clause matching math:fac(-1)
append([], L) -> L; append([H | T], L) -> [H | append(T, L)].
qsort([]) -> []; qsort([H | T]) -> qsort([ X || X <- T, X < H ]) ++ [H] ++ qsort([ X || X <- T, X >= H ]).
> Adder = fun(N) -> fun(X) -> X + N end end. #Fun<erl_eval.6.13229925> > G = Adder(10). #Fun<erl_eval.6.13229925> > G(5). 15
{'ok', timestamp(), val()}
.
{ok, {[{key(), timestamp(), val()}], boolean()}}
.
'txn'
|OpList]
"シングル" オペレーションは、 do/4 機能を利用しながら実装されています(hoodの下で). |
Tab
型式:
Tab = table()
table() = atom()
Key
型式:
Key = key()
key() = iodata()
iodata() = iolist() | binary()
iolist() = [char() | binary() | iolist()]
|
Value
型式:
Value = val()
val() = iodata()
iodata() = iolist() | binary()
iolist() = [char() | binary() | iolist()]
ExpTime
型式:
ExpTime = exp_time()
exp_time() = time_t()
time_t() = integer()
Flags
型式:
Flags = flags_list()
flags_list() = [do_op_flag() | property()]
do_op_flag() = {'testset', timestamp()}
timestamp() = integer()
property() = atom() | {term(), term()}
オペレーショナル・フラグ利用
{'testset', timestamp()}
timestamp()
と正確に等しくない場合には、オペレーションは失敗する。マイクロ・トランザクション内で利用される場合には、keyのtimestampが、timestamp()
と正確に等しくない場合には、トランザクションを停止
Timeout
型式:
Timeout = timeout()
timeout() = integer()
エラー・リターン
'key_not_exist'
{'key_exists',timestamp()}
timestamp() = integer()
{'ts_error', timestamp()}
{'testset', timestamp()}
フラグは使われており、timestampのミスマッチがあったため、オペレーションは失敗した。 リターンにおけるtimestamp()
は、 既存の keyのtimestampの現在のバリュー。
timestamp() = integer()
'invalid_flag_present'
Flags
引数に無効な do_op_flag()
が見つかったため、オペレーションは失敗した。
'brick_not_available'
{{'nodedown',node()},{'gen_server','call',term()}}
node() = atom()
オペレーショナル・フラグ利用
'get_all_attribs'
witness
flagとの組み合わせで利用され得る。
'witness'
サクセス・リターン
{'ok', timestamp(), val()}
{'ok', timestamp()}
'witness'
を使うが、'get_all_attribs'
を使わない場合のサクセス・リターン
{'ok', timestamp(), proplist()}
'witness'
と 'get_all_attribs'
の両方を使う場合のサクセス・リターン
{'ok', timestamp(), val(), exp_time(), proplist()}
'get_all_attribs'
だが 'witness'
でない場合のサクセス・リターン
For proplists, |
オペレーショナル・フラグ利用
'get_all_attribs'
witness
flagと組み合わせて使われ得る。
'witness'
{'binary_prefix', binary()}
binary()
に等しいkeyの場合だけリターンする。
{'max_bytes', integer()}
integer()
バイトを超えない程度までの多さのkeyだけにリターンする。
仮に、この flag がクライアント・リクエストにおいて明示されない場合、バリューのデフォルトは2GBまで。
{'max_num', integer()}
サクセス・リターン
{ok, {[{key(), timestamp(), val()}], boolean()}}
{ok, {[{key(), timestamp()}], boolean()}}
get_many
が'witness'
を利用するが、'get_all_attribs'
を利用しない場合のサクセス・リターン
`{ok, {[{key(), timestamp(), proplist()}], boolean()}}
get_many
が'witness'
と 'get_all_attribs'
の両方を利用する場合のサクセス・リターン
{ok, {[{key(), timestamp(), val(), exp_time(), proplist()}],
boolean()}}
get_many
が 'get_all_attribs'
だが 'witness'
でない場合のサクセス・リターン
|
For proplists, |
エラー・リターン
{txn_fail, [{integer(), do1_res_fail()}]}
do
request と、ひとつ、若しくはそれ以上の初期オペレーションで利用されたために、オペレーションは失敗した。integer()
は、リクエストの OpList
内の位置により失敗した初期オペレーションを示す。例としては、 a 2 は、失敗したリクエストの OpList
2番目のリストであることを示す。この位置識別子は、 OpList
のスタートにおいて txn()
指示子を数えてはいないことに注意。
ディレクトリを作成
$ mkdir running-directory
Hibari tarball package を解凍- "hibari-X.Y.Z-DIST-ARCH-WORDSIZE.tgz"
$ tar -C running-directory -xvf hibari-X.Y.Z-DIST-ARCH-WORDSIZE.tgz
Hibariをスタート:
$ running-directory/hibari/bin/hibari start
システムをブートストラップ:
$ running-directory/hibari/bin/hibari-admin bootstrap ok
Hibari を停止 (必要があれば後で):
$ running-directory/hibari/bin/hibari stop
"Hibari Web Administration" ページを開くことができるかを確認:
$ firefox http://127.0.0.1:23080 &
Hibari ノードにpingを成功できるかを確認:
$ running-directory/hibari/bin/hibari ping pong
シングル・ノードのHibariシステムは、ローカルホスト・アドレス 127.0.0.1. に対してハードコードされている。結果として、Hibari ノードは、ノード自身からだけ連絡可能。 |
Erlangのリモート/シェルを利用してHibariに接続
$ running-directory/hibari/erts-5.8.2/bin/erl -name hogehoge@127.0.0.1 -setcookie hibari -kernel net_ticktime 20 -remsh hibari@127.0.0.1 Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.8.2 (abort with ^G) (hibari@127.0.0.1)1>
ノードネームと一連の接続されたErlang ノードを確認
(hibari@127.0.0.1)1> node(). 'hibari@127.0.0.1' (hibari@127.0.0.1)2> nodes(). ['hogehoge@127.0.0.1'] (hibari@127.0.0.1)3>
Hibariの名前、クッキー、カーネルnet_ticktime は設定可能であり、running-directory/hibari/etc/vm.args fileのなかに置かれている。 |
"rlwrap -a running-directory/hibari/erts-5.8.2/bin/erl" ツールは、Erlang shell履歴をトラッキングし続けるために有用 (例 yum install rlwrap). |
2 つのハッシュ・プレフィックスとチェイン毎に3 つのブリックを持つ新規テーブルを作成
$ running-directory/hibari/bin/hibari-admin create-table tab2 \ -bigdata -disklogging -syncwrites \ -varprefix -varprefixsep 47 -varprefixnum 2 \ -bricksperchain 3 \ hibari@127.0.0.1 hibari@127.0.0.1 hibari@127.0.0.1
例として、キーが表す最初の部分を user’s idとする。2のハッシュ・プレフィックスは、同じチェインに格納される個々のユーザーのkeysを作成する。…しかし他のユーザーのキーと同じチェインとは限らない。
: /user1/adir/ /user1/adir/file1 /user1/adir/file3 /user1/file1 /user1/file4 /user1/xdir/ /user1/xdir/fileY : /user2/file1 : /user3/file4 :
テーブルは、Hibariの管理サーバー・ウェブページを利用して作成することもできます。 |
このエクササイズの目的は、Hibariについて学び、実装し、HibariのネイティブErlangクライアントを利用しながら、ご自身のHibariのミニ・アプリケーションをテストすることです。
15 秒程度待ち、HibariのSchema.local file とdata filesをバックアップ:
$ tar -cvzf backup.tgz running-directory/hibari/Schema.local running-directory/hibari/data/brick
HibariのSchema.local and data filesを削除:
$ rm -r running-directory/hibari/Schema.local running-directory/hibari/data/brick/*
HibariのSchema.local and data filesを修復:
$ tar -xvzf backup.tgz
Erlang Shellを使い、 Hibariのアプリケーション開発者ガイドにリストされている例を再現する
この例を実行している間、またその後にHibariの管理サーバー・ウェブページでどんな変化を見ることができますか?
Hibariの新しいAPIを実装するが、クライアント側で行う(サーバー側では無く)
⇒ 'ok'
|
'key_not_exist'
| {'ts_error', timestamp()}
| {'key_exists',timestamp()}
'testset'
flagを除く)。
'key_not_exist'
がリターン
{'testset', timestamp()}
を含み、OldKeyにtimestampのミスマッチがあり、 `{ts_error,
timestamp()}`をリターン。
proplists:delete/2
と proplists:get_value/3
は、Flags フィルタリングのために使われます。
{'testset', timestamp()}
flag は、あなたの友達です。
Mnesia は、Erlang/OTPによる分散型データベース管理システム。Mnesiaは、 dirty_update_counter/3 オペレーションをサポートする。Hibariと同様のAPIを実装し、それをクライアント側(サーバー側では無く)で行う。
⇒ {'ok', NewVal}
| 'invalid_arg_present'
| {non_integer,timestamp()}
| exit by Timeout.
'invalid_arg_present'
をリターン。
{'ok', NewVal}
がリターンされる。
{'testset', timestamp()}
flagは、あなたの友達です。
if is_integer(X) -> ...; true -> ... end.
を利用してください。
erlang:integer_to_binary/1
と
erlang:binary_to_integer/1
は、たいへんに有用 (そして、必要)。
erlang:now/0
and timer:now_diff/2
は、絶対Now timeを設定し、新しい絶対Now timeとそれぞれ比較するために使われる。Timeoutは、ミリ秒です。Nowはマイクロ秒です。
Hibariのキー・バリュー・データモデルを使って、ファイルシステムのようなクライアントAPIを実装してください。
'ok'
| {'dir_exists', timestamp()}
.
{'ok', Names}
| 'dir_not_exist'
.
'ok'
| 'dir_not_exist'
| 'dir_not_empty'
.
'ok'
| 'dir_not_exist'
| {'file_exists', timestamp()}
.
'ok'
| 'file_not_exist'
.
'ok'
| 'file_not_exist'
.
{'ok', Data}
| 'file_not_exist'
.
HibariのGitHub レポジトリとウェブページの更新を常に確認してください。
Hibari Open Source project | |
Hibari Twitter |
@hibaridb Hashtag: #hibaridb |
Gemini Twitter |
@geminimobile |
Big Data blog | |
Slideshare |