2011Q2 Tutorial - Hibari Hands On

Norton Joseph [FAMILY Given]

改訂履歴
改訂 0.12011/04/27JWN

目次

1. 概要
2. 第1部
3. Hibari 概要
4. Hibari - 特徴
5. Hibari - Erlangによる開発
6. Hibari - チェイン・レプリケーション
7. Hibari - 自動復旧
8. Hibari - 負荷分散
9. Hibari - ノード障害
10. Hibari - クラスター
11. Hibari - 負荷分散 (再)
12. Hibari - 管理サーバー
13. Hibari - チェイン
14. Hibari - クライアント
15. Hibari - 3層
16. Hibari - コンシステント・ハッシング
17. Hibari - チェイン・マイグレーション
18. Hibari - チェイン・マイグレーション (続)
19. Hibari - ログ先行書き込み
20. Hibari - クライアント API
21. Hibari - クライアント API (続)
22. 第2部
23. Erlang - 基本型
24. Erlang - 複合型
25. Erlang - その他
26. Erlang - 階乗プログラム
27. Erlang - シーケンシャル・プログラム
28. ネイティブ・クライアント - シングル・オペレーション
29. ネイティブ・クライアント - 複数オペレーション
30. ネイティブ・クライアント - 共通引数
31. ネイティブ・クライアント - 共通引数 (続)
32. ネイティブ・クライアント - 共通引数 (続)
33. ネイティブ・クライアント - 共通エラー
34. ネイティブ・クライアント - Get Flags
35. ネイティブ・クライアント - Get Rets
36. ネイティブ・クライアント - GetMany Flags
37. ネイティブ・クライアント - GetMany Rets
38. ネイティブ・クライアント - Do Rets
39. 第3部
40. Hibari - シングル・ノード・インストール
41. Hibari - シングル・ノード・スタート、ブートストラップ、停止
42. Hibari - ステイタス確認
43. Hibari - リモート・シェル
44. Hibari - 新規テーブル作成
45. Hands On エクササイズ
46. Hands On エクササイズ #1-A
47. Hands On エクササイズ #1-B
48. Hands On エクササイズ #1-C
49. Hands On エクササイズ #2
50. Hands On エクササイズ #2 - ヒント
51. Hands On エクササイズ #3
52. Hands On エクササイズ #3 - ヒント
53. Hands On エクササイズ #4 - 上級
54. Hands On エクササイズ #4 - ヒント
55. 感謝

1. 概要

第1部
  • Hibari 概要
第2部
  • Erlang 基礎
  • ネイティブ・クライアント
  • UBF 基礎 (追加)
  • UBF クライアント (追加)
第3部
  • Hibari 基礎
  • Hands On エクササイズ

2. 第1部

  • Hibari 概要

3. Hibari 概要

  • Hibariは、商用済みの分散型のキー・バリュー・ビック・データ・ストアです。
  • Hibariは、チェイン・レプリケーションとErlangにより、堅固で、高性能の分散型ストレージ・ソリューションを提供します。
  • Hibariは、データの一貫性を犠牲にすることなく、高いスループットと可用性を提供します。
  • Hibariは、オープンソースであり、通信事業者向けに開発され、通信事業者の商用環境にて数百万のユーザーに利用されています。

4. Hibari - 特徴

  • 高いパフォーマンス。特に読み出しと大きなバリュー
  • テーブル毎のオプションとして、RAM+diskベース か disk-onlyのバリュー・ストレージ (#)
  • キー毎の有効期限とキー毎のカスタム・メタデータをサポート
  • 複数キーのレンジリミット内でのアトミック処理をサポート
  • "test-and-set" タイプの運用を容易にするキー・タイムスタンプの仕組み
  • システムを拡張する際の自動データ・リバランス
  • ライブ・コード・アップグレードをサポート
  • 複数クライアントAPIを実装

# キー単位 オプション実装されているが、商用設定には未展開。

5. Hibari - Erlangによる開発

  • Hibariのサーバーは、すべてErlangで開発。HibariのクライアントはErlangでも、他のプログラミング言語でも開発可能。
  • Erlangは、多目的プログラミング言語であり、信頼性ある高いパフォーマンスの分散システムをサポートするために特別に設計されたランタイム環境。
  • Erlangの主な利点は、

    • Concurrency (同時並行性)
    • Distribution (分散)
    • Robustness (堅牢)
    • Portability (移植性)
    • ホット・コード・アップグレード
    • 予測可能なガベージコレクション

6. Hibari - チェイン・レプリケーション

images/chain_replication.png

  • チェイン・レプリケーションは、データの一貫性を損なうことなく、冗長性と高可用性を提供する技術。
  • 書き込みリクエストは、"ヘッド" から "ミドル"、そして "テイル" ブリックの順で行われる。
  • 読み出しリクエストは、"テイル" ブリックに行う。
  • チェインの長さは設定可能で、レプリケーションの度合を決める。
  • コンシステント・ハッシングにより、キー・スペースは複数のストレージ "チェイン" 全体に分割される。
  • 全てのキーやキーのプレフィックスはコンシステント・ハッシングに依存する。

7. Hibari - 自動復旧

images/automatic_failover.png

  • Hibariは、チェインの中での障害を検知し、自動的にメンバーブリックの役割を調整する。
  • 仮に、ヘッド・ブリックがダウンした場合には、ミドル・ブリックが自動的にヘッド・ブリックの役割を引き受ける。
  • 仮に、新しいヘッド・ブリックにも障害があった場合、残るブリックがヘッドとテイル両方の役割を行う。
  • チェイン・レプリケーションの特性により、Hibariはブリック障害の際にも強い一貫性を提供できる。

8. Hibari - 負荷分散

images/load_balanced_chains.png

  • ヘッド・ブリックとテイル・ブリックはミドル・ブリックよりも大きな負荷がかかる。
  • 物理マシン全体としての役割とチェインの負荷分散は、ハードウェア・リソースを有効に活用できる。

9. Hibari - ノード障害

images/automatic_failover_2.png

物理的なノード障害の場合、ブリックは自動的に役割をシフトし、それぞれのチェインはクライアントにサービスを提供し続ける。

チェイン・リペアのプロセス
  1. 障害ノードが再開される。
  2. 障害ブリックが再開され、チェインのエンドに移される。
  3. 障害ブリックは、"公式テイル"に自身を修復する。
  4. 修復ブリックは元のポジションに戻され、通常サービスを再開する。

10. Hibari - クラスター

images/cap-01.png

11. Hibari - 負荷分散 (再)

images/chain-01.png

12. Hibari - 管理サーバー

images/cap-02-admin.png

13. Hibari - チェイン

images/cap-02-chain.png

14. Hibari - クライアント

images/cap-02-client.png

15. Hibari - 3層

トップ層
コンシステント・ハッシング
ミドル層
チェイン・レプリケーション
ボトム層
ストレージ・ブリック

images/logical-architecture1.png

16. Hibari - コンシステント・ハッシング

  • Hibari クライアントは、どのチェインがキーのオペレーションを取り扱うべきかを計算するアルゴリズムを利用します。
  • クライアントは、Hibari管理サーバーの更新を経て、この情報を得ます。
  • これらの更新は、大部分のユースケースにおいて、クライアントにそのリクエストを正しいサーバーに直接送らせます。サーバーはクライアントの計算が正しいかを証明するアルゴリズムを利用します。
  • 仮に、クライアントが誤ったブリックにオペレーションを送る場合、ブリックは正しいブリックにオペレーションを転送します。

17. Hibari - チェイン・マイグレーション

images/chain-migration-3to4.png

データを再配置するきっかけ:

  • チェインはクラスターから追加されるか、削除されます。
  • ブリック・ハードウェアが変更されます。(例)ディスクやRAM容量の追加。
  • テーブルのコンシステント・ハッシング・アルゴリズム設定における変更は、データ(定義により)を他のチェインに移します。

18. Hibari - チェイン・マイグレーション (続)

images/migration-3to4.png

キー・ポイント
  • 一つの場所から他にデータを動かすことを最小限にする。
  • サービスインパクトを最小限にするためのレート管理機能をサポートする。
  • マイグレーションの前に、 "テスト" し、キー分散を"カスタマイズ" できる。

19. Hibari - ログ先行書き込み

images/private-and-common-logs.png

  • サーバー毎の共有 "common log"。 fsync() システムコール経由でサーバー・ノード内全ての論理ブリックに永続的保証を提供する。
  • ブリック毎の個別 "private logs"。 論理ブリックにおいてキーを認識する全てのメタデータは論理ブリックのprivate logに格納される。

20. Hibari - クライアント API

キー・バリュー・ストアであることから、HibariのコアデータモデルとクライアントAPIモデルは、設計においてシンプル。:

  • blobベースのキー・バリュー・ペア

    • キー: 典型的に、 "/' によってセパレートされるパスのような名前
    • バリュー: バイナリー blobs (しばしば、 Erlang termによりシリアライズされる)
  • オペレーション

    • 挿入 (add, set, replace)
    • 削除 (delete)
    • 検索 (get, get_many)
  • 辞書配列ソートテーブル
  • 個別のチェインにアトミックな "マイクロ・トランザクション" の実装に(しばしば)利用されるキー・プレフィックス

21. Hibari - クライアント API (続)

Hibariは、複数のクライアント API実装をサポート:

  • Native Erlang
  • Universal Binary Format (UBF/EBF)
  • Thrift
  • Amazon S3
  • JSON-RPC

Java, C/C++, Python, Ruby, Erlangを含む様々な言語におけるHibariクライアント・アプリケーション開発が可能

22. 第2部

  • 休憩 #1

    • 10 分休憩
  • Erlang 基礎
  • ネイティブ・クライアント
  • UBF 基礎 (追加)
  • UBF クライアント (追加)

23. Erlang - 基本型

2種類の数値リテラル, integersfloats.
Atom

atom はリテラルで、名前を持つ定数。atomは、小文字で開始する場合や、アルファベット、数値、アンダースコア (_), や @以外の文字を含む場合には、シングル・クォート (') で囲まれるべき。

hello
phone_number
'Monday'
'phone number'
'hello'
'phone_number'
Bit StringとBinary

bit string は、非型式メモリーの領域を格納するために使われる。8で割り切れるビットからなるbit string は、 binary と呼ばれる。

<<10,20>>
<<"ABC">>

24. Erlang - 複合型

Term
あらゆるデータ型式のなかのひとつのデータは、 term と呼ばれる。
Tuple

tuple は、中括弧で囲まれる固定数をもつ複合データ型式。:

{Term1,...,TermN}
List

list は、鍵括弧で囲まれる変数をもつ複合データ型式。:

[Term1,...,TermN]
String
Stringsは、2重括弧 (") で囲まれるが、Erlangにおいては真のデータ型式ではない。代わりに、string の"hello" は、 list [$h,$e,$l,$l,$o] に短縮される。すなわち、 [104,101,108,108,111] 。

25. Erlang - その他

Boolean
Erlangには、Boolean データ型式がない。代わりに、atomsの truefalse がBoolean values を表示するために使われる。
None or Null
Erlangには、このような型式はない。 しかし、atomの undefined は、しばしば(慣習として)この目的のために使われる。
Pid
プロセス識別である pid は、Erlangプロセスを識別する。
Reference
reference は、Erlang ランタイム・システム独自の表現。
Fun
fun は、関数オブジェクト。

_… 数点追加_

26. Erlang - 階乗プログラム

ファイル "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)

27. Erlang - シーケンシャル・プログラム

Append
append([],      L) -> L;
append([H | T], L) -> [H | append(T, L)].
QuickSort
qsort([]) -> [];
qsort([H | T]) ->
  qsort([ X || X <- T, X < H ]) ++
        [H] ++
        qsort([ X || X <- T, X >= H ]).
Adder
> 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

28. ネイティブ・クライアント - シングル・オペレーション

brick_simple:add(Tab, Key, Value, ExpTime, Flags, Timeout)
⇒ ok.
brick_simple:replace(Tab, Key, Value, ExpTime, Flags, Timeout)
⇒ ok.
brick_simple:set(Tab, Key, Value, ExpTime, Flags, Timeout)
⇒ ok.
brick_simple:get(Tab, Key, Flags, Timeout)
{'ok', timestamp(), val()}.
brick_simple:get_many(Tab, Key, MaxNum, Flags, Timeout)
{ok, {[{key(), timestamp(), val()}], boolean()}}.
brick_simple:delete(Tab, Key, Flags, Timeout)
⇒ ok.

29. ネイティブ・クライアント - 複数オペレーション

brick_simple:do(Tab, OpList, OpFlags, Timeout)
⇒ [OpRes()].
2つの特色
  • ノーマル - OpList
  • マイクロ・トランザクション - ['txn'|OpList]
[ヒント]

"シングル" オペレーションは、 do/4 機能を利用しながら実装されています(hoodの下で).

30. ネイティブ・クライアント - 共通引数

Tab

  • ノードの名前.
  • 型式:

    • Tab = table()
    • table() = atom()

Key

  • ペアのバリューに関連している、テーブルのキー
  • 型式:

    • Key = key()
    • key() = iodata()
    • iodata() = iolist() | binary()
    • iolist() = [char() | binary() | iolist()]
[注記]

Key は、内部的に常にbinaryに変換されます。

31. ネイティブ・クライアント - 共通引数 (続)

Value

  • keyに紐づくValue.
  • 型式:

    • Value = val()
    • val() = iodata()
    • iodata() = iolist() | binary()
    • iolist() = [char() | binary() | iolist()]

ExpTime

  • Unix time_t() として表現される、keyが期限切れとなる時間
  • オプション; 0 までをデフォルト (有効期限無し).
  • 型式:

    • ExpTime = exp_time()
    • exp_time() = time_t()
    • time_t() = integer()

32. ネイティブ・クライアント - 共通引数 (続)

Flags

  • データベースのkey-value ペアに関連するオペレーショナル・フラグとプロパティ・フラグのリスト。 カスタム・プロパティ・フラグの多用はRAMベースのストレージによって、抑制される。
  • 型式:

    • Flags = flags_list()
    • flags_list() = [do_op_flag() | property()]
    • do_op_flag() = {'testset', timestamp()}
    • timestamp() = integer()
    • property() = atom() | {term(), term()}
  • オペレーショナル・フラグ利用

    • {'testset', timestamp()}

      • 既存の keyのtimestamp が timestamp() と正確に等しくない場合には、オペレーションは失敗する。マイクロ・トランザクション内で利用される場合には、keyのtimestampが、timestamp() と正確に等しくない場合には、トランザクションを停止

Timeout

  • ミリ秒でオペレーション・タイムアウト
  • オプション; 15000までをデフォルト
  • 型式:

    • Timeout = timeout()
    • timeout() = integer()

33. ネイティブ・クライアント - 共通エラー

エラー・リターン

  • 'key_not_exist'

    • keyが存在しないため、オペレーションは失敗した。
  • {'key_exists',timestamp()}

    • keyがすでに存在しているため、オペレーションは失敗した。
    • timestamp() = integer()
  • {'ts_error', timestamp()}

    • {'testset', timestamp()} フラグは使われており、timestampのミスマッチがあったため、オペレーションは失敗した。 リターンにおけるtimestamp() は、 既存の keyのtimestampの現在のバリュー。
    • timestamp() = integer()
  • 'invalid_flag_present'

    • Flags 引数に無効な do_op_flag() が見つかったため、オペレーションは失敗した。
  • 'brick_not_available'

    • このkey を受け持つチェインの長さが現在ゼロで利用できないためにオペレーションは失敗した。
  • {{'nodedown',node()},{'gen_server','call',term()}}

    • リクエストを処理するサーバー・ブリックが停止したか、クライアントとサーバー間でネットワーク分断が起きたため、オペレーションは失敗した。管理サーバーが障害を検知し、チェイン修理を行うステップをとるという前提で、クライアントは短い遅延後にクエリを再送する。
    • node() = atom()
  • timeoutにより終了。

34. ネイティブ・クライアント - Get Flags

  • オペレーショナル・フラグ利用

    • 'get_all_attribs'

      • keyの全ての属性をリターン。witness flagとの組み合わせで利用され得る。
    • 'witness'

      • 結果として、バリューの blob をリターンさせない。このフラグは、ブリックがこのリクエストを満たすディスクアクセスを要求していないことを保証する。

35. ネイティブ・クライアント - Get Rets

サクセス・リターン

  • {'ok', timestamp(), val()}

    • デフォルトの反応
  • {'ok', timestamp()}

    • get が'witness' を使うが、'get_all_attribs' を使わない場合のサクセス・リターン
  • {'ok', timestamp(), proplist()}

    • get が 'witness''get_all_attribs' の両方を使う場合のサクセス・リターン
  • {'ok', timestamp(), val(), exp_time(), proplist()}

    • get が 'get_all_attribs' だが 'witness' でない場合のサクセス・リターン
[注記]

For proplists, {val_len,Size::integer()} は、つねにリターンされる。

36. ネイティブ・クライアント - GetMany Flags

  • オペレーショナル・フラグ利用

    • 'get_all_attribs'

      • それぞれのkeyの全属性をリターン。witness flagと組み合わせて使われ得る。
    • 'witness'

      • 結果として、バリューのDo not return the value blobsをリターンさせない。このflagは、ブリックがこのリクエストを満たすディスク・アクセスを要求しないことを保証する。
    • {'binary_prefix', binary()}

      • binary prefixをもつkeysが正確に binary() に等しいkeyの場合だけリターンする。
    • {'max_bytes', integer()}

      • 対応するバリューのblobsのサイズの合計が integer() バイトを超えない程度までの多さのkeyだけにリターンする。 仮に、この flag がクライアント・リクエストにおいて明示されない場合、バリューのデフォルトは2GBまで。
    • {'max_num', integer()}

      • リターンするkeysの最大値。デフォルトは10. Note: このflagは、意図的に MaxNum 引数に重複

37. ネイティブ・クライアント - GetMany Rets

サクセス・リターン

  • {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' でない場合のサクセス・リターン
[注記]

boolean() はチェインがさらに多くのkeyを有しているかどうかを示す。

[注記]

For proplists, {val_len,Size::integer()} は、つねにリターンされる。

38. ネイティブ・クライアント - Do Rets

エラー・リターン

  • {txn_fail, [{integer(), do1_res_fail()}]}

    • トランザクション・セマンティックが、失敗したトランザクション内のdo request と、ひとつ、若しくはそれ以上の初期オペレーションで利用されたために、オペレーションは失敗した。integer() は、リクエストの OpList 内の位置により失敗した初期オペレーションを示す。例としては、 a 2 は、失敗したリクエストの OpList 2番目のリストであることを示す。この位置識別子は、 OpList のスタートにおいて txn() 指示子を数えてはいないことに注意。

39. 第3部

  • 休憩 #2

    • 10 分間休憩
  • Hibari 基礎
  • Hands On エクササイズ

40. Hibari - シングル・ノード・インストール

  • ディレクトリを作成

    $ 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
  • X.Y.Z はリリースバージョン ⇒ "0.1.4"
  • DIST は、リリース・ディストリビューション ⇒ "fedora14"
  • ARCH はリリース・アーキテクチュア ⇒ "x86_64-unknown-linux-gnu"
  • WORDSIZE は、リリース・ワードサイズ ⇒ "64"

41. Hibari - シングル・ノード・スタート、ブートストラップ、停止

  • Hibariをスタート:

    $ running-directory/hibari/bin/hibari start
  • システムをブートストラップ:

    $ running-directory/hibari/bin/hibari-admin bootstrap
    ok
  • Hibari を停止 (必要があれば後で):

    $ running-directory/hibari/bin/hibari stop

42. Hibari - ステイタス確認

  • "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 ノードは、ノード自身からだけ連絡可能。

43. 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).

44. Hibari - 新規テーブル作成

  • 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の管理サーバー・ウェブページを利用して作成することもできます。http://localhost:23080/ を開き、"Add a table" リンクをクリックしてください。

45. Hands On エクササイズ

このエクササイズの目的は、Hibariについて学び、実装し、HibariのネイティブErlangクライアントを利用しながら、ご自身のHibariのミニ・アプリケーションをテストすることです。

46. Hands On エクササイズ #1-A

  1. Hibariをインストール
  2. Hibariをスタートし、ブートストラップ
  3. 15 秒程度待ち、HibariのSchema.local file とdata filesをバックアップ:

    $ tar -cvzf backup.tgz running-directory/hibari/Schema.local running-directory/hibari/data/brick
  4. Hibariの状態を確認
  5. Erlang shellを使いHibariに接続
  6. 上記で述べたtab2 を作成
  7. Hibariの管理サーバー・ウェブページを開く
  8. tab1とtab2の間に同じものと違うもののリストを作成
  9. 管理サーバー・ウェブページから他に学ぶことができることは何でしょうか?

47. Hands On エクササイズ #1-B

  1. Hibariを停止
  2. HibariのSchema.local and data filesを削除:

    $ rm -r running-directory/hibari/Schema.local running-directory/hibari/data/brick/*
  3. HibariのSchema.local and data filesを修復:

    $ tar -xvzf backup.tgz
  4. Hibariをスタート
  5. Hibariの状態を確認
  6. Hibariの管理サーバー・ウェブページを開く
  7. いま、どのテーブルが存在しているでしょうか?
  8. 上記で述べたtab2 (再び) を作成
  9. Hibariを停止し、スタート
  10. チェインとブリックスの状況をフォロー
  11. 何が起きているのでしょうか?
  12. チェインとブリックそれぞれの履歴はどうなっているのでしょうか?

48. Hands On エクササイズ #1-C

Erlang Shellを使い、 Hibariのアプリケーション開発者ガイドにリストされている例を再現する

この例を実行している間、またその後にHibariの管理サーバー・ウェブページでどんな変化を見ることができますか?

49. Hands On エクササイズ #2

Hibariの新しいAPIを実装するが、クライアント側で行う(サーバー側では無く)

rename(Tab, OldKey, Key, ExpTime, Flags, Timeout)

'ok' | 'key_not_exist' | {'ts_error', timestamp()} | {'key_exists',timestamp()}

  • この関数は、OldKeyに関連した既存のバリューを新しいkeyに名前変更し、OldKeyを削除。. Flags of the OldKeyのFlagsは無視され、Flags引数に置換される ('testset' flagを除く)。
  • OldKeyが存在しなければ、 'key_not_exist' がリターン
  • OldKeyが存在すれば、 Flagsは {'testset', timestamp()} を含み、OldKeyにtimestampのミスマッチがあり、 `{ts_error, timestamp()}`をリターン。
  • Keyが存在すれば、`{key_exists,timestamp()}`をリターン。

50. Hands On エクササイズ #2 - ヒント

  1. 最初の実装において、トランザクショナル do/4 オペレーションは気にしないでください。
  2. Erlang/OTP proplists:delete/2proplists:get_value/3 は、Flags フィルタリングのために使われます。
  3. {'testset', timestamp()} flag は、あなたの友達です。
  4. 冒険的と感じる場合には、 トランザクショナル do/4 オペレーションで実装してみてください。OldKey とKeyに設置しなければならないのはどんな制約でしょうか?

51. Hands On エクササイズ #3

Mnesia は、Erlang/OTPによる分散型データベース管理システム。Mnesiaは、 dirty_update_counter/3 オペレーションをサポートする。Hibariと同様のAPIを実装し、それをクライアント側(サーバー側では無く)で行う。

update_counter(Tab, Key, Incr, Timeout)

{'ok', NewVal} | 'invalid_arg_present' | {non_integer,timestamp()} | exit by Timeout.

  • この関数は、正か負のintegerのカウンターを更新する。しかし、カウンターはゼロ以下にはならない。
  • Incrが、integerで無い場合には, 'invalid_arg_present' をリターン。
  • 2人(それ以上)が同時にupdate_counter/3 を実行する場合、 両方の更新はどちらかひとつを失うというリスク無しに有効になります。カウンターの新しいバリュー {'ok', NewVal} がリターンされる。
  • Keyが存在しない場合には、0よりお大きければ新しいカウンターはバリュー Incrを作成し、そうでない場合は0に設定される。
  • Keyが存在するけれども、 integerがゼロより大きいか等しくなければ、 {non_integer, timestamp()}をリターンする。
  • カウンターの更新が特定のtimeoutを超えた場合には, Timeoutにより終了する。

52. Hands On エクササイズ #3 - ヒント

  1. {'testset', timestamp()} flagは、あなたの友達です。
  2. termが integer か否かを確かめるためには、if is_integer(X) -> ...; true -> ... end. を利用してください。
  3. Erlang primitivesのerlang:integer_to_binary/1erlang:binary_to_integer/1 は、たいへんに有用 (そして、必要)。
  4. Erlang primitive のerlang:now/0 and timer:now_diff/2 は、絶対Now timeを設定し、新しい絶対Now timeとそれぞれ比較するために使われる。Timeoutは、ミリ秒です。Nowはマイクロ秒です。

53. Hands On エクササイズ #4 - 上級

Hibariのキー・バリュー・データモデルを使って、ファイルシステムのようなクライアントAPIを実装してください。

mkdir(Tab, Path, Timeout)
'ok' | {'dir_exists', timestamp()}.
listdir(Tab, Path, Timeout)
{'ok', Names} | 'dir_not_exist'.
rmdir(Tab, Path, Timeout)
'ok' | 'dir_not_exist' | 'dir_not_empty'.
create(Tab, Path, Timeout)
'ok' | 'dir_not_exist' | {'file_exists', timestamp()}.
rmfile(Tab, Path, Timeout)
'ok' | 'file_not_exist'.
writefile(Tab, Path, Data, Timeout)
'ok' | 'file_not_exist'.
readfile(Tab, Path, Timeout)
{'ok', Data} | 'file_not_exist'.

54. Hands On エクササイズ #4 - ヒント

  • どのように、ファイルを表現しますか?
  • どのように、ディレクトリーを表現しますか?
  • どのように、あるディレクトリー内のファイルを探しますか?…ディレクトリーツリーの下は?
  • どのように、ディレクトリーが空かどうかを効果的に確認しますか?
  • どのように、timestamps のtest-n-set を利用しますか?

55. 感謝

HibariのGitHub レポジトリとウェブページの更新を常に確認してください。

Hibari Open Source project

https://github.com/hibari

Hibari Twitter

@hibaridb Hashtag: #hibaridb

Gemini Twitter

@geminimobile

Big Data blog

http://hibari-gemini.blogspot.com/

Slideshare

http://www.slideshare.net/geminimobile