スケーラブルなシステムのためのhbaseスキーマ設計 #hcj13w
DESCRIPTION
Cloudera HBase トレーニング: http://tiny.cloudera.com/jptraininghbase Hadoop Conference Japan 2013 Winter で発表した、HBaseのスキーマ設計に関する資料です。 Cloudera の HBase サポート、Cloudera Enterprise RTD http://tiny.cloudera.com/jpcertdTRANSCRIPT
1
スケーラブルなシステムのための HBaseスキーマ設計
Cloudera株式会社 カスタマーオペレーションズエンジニア 嶋内 翔 2013年1月21日
自己紹介
• 嶋内 翔(しまうち しょう) • 2011年4月にClouderaの最初の日本人社員として入
社 • カスタマーオペレーションズエンジニアとしてテクニ
カルサポート業務を担当 • email: [email protected] • twi=er: @shiumachi
2
Agenda
• Apache HBase とは • スキーマ設計の話の前に • HBase ストレージアーキテクチャ • スキーマ設計のポイント
3
セッション概要
• Hadoop 上で動作する分散ストレージシステム HBase を活用するためのスキーマ設計のポイントについて紹介します
• ゴール • 性能が出る、正しいHBaseのスキーマ設計ができるように
なること • アンチパターンを知り、誤ったスキーマ設計を避けるよう
になること
4
対象者・レベル
• 対象者 • HBase の構築・運用担当者 • HBase アプリケーションの開発者
• 対象レベル: 中級 • Hadoop (特に HDFS) について、アーキテクチャをある程度
理解している
5
本セッションで取り扱わない内容 (1) HDFSの信頼性
• HBaseはデータの信頼性をファイルシステムに依存しています
• HDFSは十分信頼性が高いです • 数年以上の稼動実績 • HDFS HA によるSPOFの排除
• 詳細は下記スライドを参照してください • Cloudera Manager4.0とNameNode-‐HAセミナー資料
• h=p://www.slideshare.net/Cloudera_jp/cloudera-‐manager4namenodeha
• CDH4.1オーバービュー(HA機能についての説明があります)
• h=p://www.slideshare.net/Cloudera_jp/cdh41
6
本セッションで取り扱わない内容 (2) Hadoop/HBaseの運用・チューニング
Cloudera Managerを使えば1時間でCDHクラスタの構築ができ、管理も非常に簡単です
HBaseを使うなら Cloudera Enterprise
(CDH + Cloudera Manager) を選びましょう
ダウンロードはこちら
h=p://www.cloudera.com/downloads/
7
8
Apache HBase とは
HBase
• HDFS 上で動作する NoSQL • Google の開発した NoSQL BigTable に基づいて作成され
ている • HDFS が苦手とする低レイテンシのアクセスや小さいファ
イルの操作を得意とする
h=p://ja.fotopedia.com/items/flickr-‐1999559141
なぜHBaseを使うのか
• シャーディングをサポートしてる • 自動シャーディング • コマンド一発で手動シャーディング
• 書き込みが高速で、しかもスケールアウト可能 • データの耐障害性も確保されてる
• これはHadoopのファイルシステムHDFSの機能
HBaseのデータ構造
キーバリューがソートされて並んでいる
行キー 値 列ファミリ 列 タイム スタンプ
r1 ‘python’ cf1 c1 1000
r1 ‘php’ cf1 c2 1000
r1 ‘ruby’ cf2 c1 1000
r2 ‘java’ cf1 c2 1000
HBaseのテーブル構造(概要)
• 行キーの一定範囲ごとに別ファイルに分割 • この範囲のことをリージョンという
• 1リージョンには列ファミリの数以上のストアファイルが存在 • ここではかなり簡略化して説明している。詳細は後述
ストアファイル ストアファイル
ストアファイル ストアファイル
ストアファイル ストアファイル
リージョン a -‐ c
リージョン d -‐ f
リージョン h -‐ j
列ファミリ1 列ファミリ2
HBaseの構成図
データノード データノード データノード データノード データノード データノード データノード データノード データノード
クライアント
ブロック1 ブロック1 ブロック1
ブロック2 ブロック2 ブロック2
ブロック3 ブロック3 ブロック3
リージョンサーバ
リージョンc
リージョンサーバ
リージョンa
リージョンサーバ
リージョンb
※マスタサーバは存在するが、 データ通信には使わない
HBaseの動作概要
データノード データノード データノード データノード データノード データノード データノード データノード データノード
クライアント
ブロック1 ブロック1 ブロック1
ブロック2 ブロック2 ブロック2
ブロック3 ブロック3 ブロック3
リージョンサーバ
リージョンc
リージョンサーバ
リージョンa
リージョンサーバ
リージョンb
HDFSと同様、クライアントはマスタを介さず直接リージョンサーバと通信する
リージョンサーバはHDFSのクライアントとして データノードと通信する
15
スキーマ設計の話の前に
究極のベストプラクティス、それは……
16
17
h=p://ja.fotopedia.com/items/flickr-‐1999559141
HBaseを使わない (必要がない限り)
18
h=p://ja.fotopedia.com/items/flickr-‐1999559141
HBase にはない機能がいっぱい
• JOINがない • セカンダリインデックスも当然ない • テーブル間トランザクションがない • etc.
19
RDBMSは超優秀だし最近はハードウェアも安いので 必要ない限りはRDBMS使いましょう
じゃあどんなときにHBaseを使えばいいの?
20
じゃあどんなときにHBaseを使えばいいの?
21
大量のデータがあるとき!
じゃあどんなときにHBaseを使えばいいの?
• サーバ1台のメモリに載りきらない • サーバ1台のディスクに入りきらない • etc. • 最近のサーバだとメモリ100GB、ディスク10TB(RAID5)ぐ
らいなら余裕のはず • Hadoopを既に使っている人は大量データがあるはずな
ので利用の検討はあり
22
大量のデータがあるとき!
HBaseとRDBの比較
• RDBMSが高機能 • きちんとDB設計すればほ
ぼどんなクエリにも対応可能
• スケールしない • ストレージ容量 • 書き込み
• 非正規化前提 • 特定のクエリに特化して
設計 • 用途を絞ってしまえば、
容量や読み書きがスケールするので非常に強力
• Hadoop との連携がしやすい
23
RDB HBase
RDBとHBaseにおけるスキーマ設計の違い
24
RDBとHBaseにおけるスキーマ設計の違い
25
論理設計まではほぼ同じ
• 論理データモデルが間違ってたらこの先の議論は無意味
• RDBとHBaseの違いは物理表現レベルの話
しかし、設計段階でも物理表現を知ることは 重要
• HBaseはユースケースやアクセスパターンに基づいて自動的に最適化したりしない
• HBaseの実装を知らないと正しいスキーマ設計ができない
• このセッションではまずHBaseのストレージアーキテクチャを理解し、その上でスキーマ設計の話に移る
26
27
HBase ストレージアーキテクチャ
HBaseテーブル
28
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
HBaseテーブル
• 行と列によるテーブル構造 • 行は一定範囲ごとに「リージョン」という単位で区切られて
いる • 列は「列ファミリ」という単位でグループ化されている
• セル = 行と列の交点 • セルはタイムスタンプを持っている
• バージョンとタイムスタンプはほぼ同じ意味
29
HBaseテーブル
30
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
HBaseテーブル
31
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
テーブルに対する行、列、そして行と列の交差する部分のセル
論理的なテーブル構造は基本的にRDBと変わらない
HBaseテーブル
32
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1 (r3, A:b) ver.2
リー
ジョ
ン1
リー
ジョ
ン2
HBaseテーブル
33
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1 (r3, A:b) ver.2 (r3, A:b) ver.3
リー
ジョ
ン1
リー
ジョ
ン2
HBaseテーブル
34
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1 (r3, A:b) ver.2 (r3, A:b) ver.3
リー
ジョ
ン1
リー
ジョ
ン2
セルには複数のバージョンを格納することができる
リージョンと列ファミリ
• テーブルは複数のリージョンで構成されている • リージョン = 一定範囲の行キーの集合 • リージョンは行キーのスタートキーとエンドキーで区分け
される • それぞれのリージョンは別々のリージョンサーバに割り当
てられている
• 列(カラム)は、列ファミリと列が存在する • 列ファミリごとに別々の物理ファイルが作成される • 「列ファミリ:列」の記述を列修飾子というが、これで単に列
ということも多い
35
リージョンと列ファミリ
36
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
リージョンと列ファミリ
37
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
テーブルは複数のリージョンで 構成されている
リージョンと列ファミリ
38
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
列ファミリごとに別々の物理ファイルに格納される
リージョンと列ファミリ
39
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンと列ファミリ
40
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンはスタートキーとエンドキーで範囲を決定する
エンドキーは含まないので注意
リージョンと列ファミリ
41
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
リージョンと列ファミリ
42
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
リージョンはスレーブノード(リージョンサーバ)に別々に配置される
リージョンと列ファミリ
43
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
MemStore1 MemStore2 MemStore3 MemStore4
リージョンと列ファミリ
44
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
MemStore1 MemStore2 MemStore3 MemStore4
列ファミリごとにメモリストア(MemStore) が作られる
書き込みを行う場合、先行書き込みログ(WAL)に書き込んだあとはこのMemStoreに書き込まれる MemStoreはメモリ上にしか存在しない
メモリストアはリージョン☓列ファミリごとに存在する
リージョンと列ファミリ
45
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
MemStore1 MemStore2 MemStore3 MemStore4
HDFS
HFile 1 HFile 1 HFile 1 HFile 1 HFile 1 HFile 2
HFile 1 HFile 1 HFile 3 HFile 1 HFile 1 HFile 4
リージョンと列ファミリ
46
リージョン1 [r1, r4)
リージョン2 [r4, r6)
リージョンサーバA リージョンサーバB
リージョン1 リージョン2
MemStore1 MemStore2 MemStore3 MemStore4
HDFS
HFile 1 HFile 1 HFile 1 HFile 1 HFile 1 HFile 2
HFile 1 HFile 1 HFile 3 HFile 1 HFile 1 HFile 4 HFileは HDFS 上に格納される データブロックの複製や配置は
全てHDFS側で管理 (図ではHDFSのレプリカは省略)
MemStoreに対し複数のHFileが存在する Memstoreからフラッシュされるたびに作成され、
コンパクションによってまとめられる
論理テーブルから物理ファイルへ
47
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
リージョン1 [r1, r4)
リージョン2 [r4, r6)
論理テーブルから物理ファイルへ
48
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
MemStore 1
MemStore 3
MemStore 2
MemStore 4
論理テーブルから物理ファイルへ
49
列ファミリA 列ファミリB 列a 列b 列c 列a 列b
行 r1
行 r2
行 r3
行 r4
行 r5
(r3, A:b) ver.1
リー
ジョ
ン1
リー
ジョ
ン2
HFile 3-‐1
HFile 1-‐3 HFile 2-‐2
HFile 4-‐5
HBase テーブルと物理レイアウト
• テーブルでは、辞書順に行をソートしている • 全ての値は行キー、列ファミリ、列修飾子、タイムス
タンプと一緒に保存される • テーブルのスキーマは列ファミリのみ定義している
• それぞれの列ファミリは任意の数の列を格納可能 • 列ファミリと異なり、スキーマ定義は不要
• それぞれのセル(行と列の交点)は任意の数のバージョンを格納可能
• セルは挿入されたときにしか作成されないのでNULLはコストゼロ
• テーブル名以外はすべて byte[] として格納される
50
HBase テーブルと物理レイアウト
以下のようなテーブルを例に考える
51
r1
cf1:c1
‘python’ ts = 100
cf1:c2 cf2:c1 cf1:c2
‘php’ ts = 100
‘ruby’ ts = 100
r2 ‘java’ ‘scala’ ts = 100
‘scala’ ts = 100
‘java’ ts = 90
HBase テーブルと物理レイアウト
52
ストアファイル cf1
r1:cf1:c1:100:‘python’
r1:cf1:c2:100:‘php’
r2:cf1:c1:100:‘scala’
r2:cf1:c1:90:‘java’
ストアファイル cf2
r1:cf2:c1:100:‘ruby’
ストアファイルにはこのように保存されている
HBase テーブルと物理レイアウト
53
r1:cf1:c1:100:‘python’
r1:cf1:c2:100:‘php’
r2:cf1:c1:100:‘scala’
r2:cf1:c1:90:‘java’
ストアファイル cf2
r1:cf2:c1:100:‘ruby’
ストアファイル cf1
ストアファイルはリージョン☓列ファミリで作る 列ファミリはスキーマ定義時に一緒に定義する
HBase テーブルと物理レイアウト
54
ストアファイル cf1
r1:cf1:c2:100:‘php’
r2:cf1:c1:100:‘scala’
r2:cf1:c1:90:‘java’
ストアファイル cf2
r1:cf2:c1:100:‘ruby’ r1:cf1:c1:100:‘python’
行キー:列ファミリ:列:タイムスタンプ:値 これらが全て1つのデータで格納されている
行キー 列ファミリ 列
タイムスタンプ 値
55
スキーマ設計のポイント
スキーマ設計
• 最高のパフォーマンスを得るのに正しいスキーマ設計は不可欠
• HBaseでの正しいスキーマ設計にはストレージアーキテクチャの知識が不可欠
• これまでのアーキテクチャの説明を踏まえて、スキーマ設計のポイントを説明します
56
スキーマ設計の前に(再)
• 論理設計までは同じです • 設計する前に、「どういう問い合わせをしたいか」を
きちんと考えましょう • ユーザ同士のソーシャルグラフを見たい • ユーザ単位のメッセージを一括取得したい • etc.
57
DDI(でぃーでぃーあい)
• Denormalizajon(非正規化) • 複数のエンティティのリレーションを一つのテーブルで表現する • 一回の読み込みでそのリレーションに関するデータ取得が可能
• Duplicajon(複製) • Intelligent Keys(インテリジェントキー)
• 属性の組み合わせを行キーとすることで検索を容易にする • RDBにおける複合キーのようなもの
• の略 • 詳細は 「Cloud Data Structure Diagramming Techniques and
Design Pa=erns」を参照 • h=ps://www.data-‐tacjcs-‐corp.com/index.php/component/
jdownloads/finish/22-‐white-‐papers/68-‐cloud-‐data-‐structure-‐diagramming
58
非正規化
• HBaseにはJOINがない • JOINなしでエンティティ間のリレーションを表現する
方法は2つ • 自力でJOINを実装する
• 極めて困難。ていうか無理
• データを非正規化する
• 非正規化 = 2つの論理エンティティで1つの物理表現を共有すること
59
非正規化の例
60
Order
id amount customer_id item_id
Item
id name price
Customer
id name
普通のリレーショナルモデルの設計 これを……
全部くっつける!
61
Order
id amount customer_id item_id
Item
id name price
Customer
id name
Order order_id order_amount customer_id customer_name item_id item_name item_price
非正規化のメリットとデメリット
• メリット • あらかじめ非正規化しておいたリレーションに関するクエ
リは、たとえ大量のデータであっても超高速に結果が返ってくる
• デメリット • 更新が大変 • 非正規化していないエンティティ同士のリレーションに関
するクエリは、JOINがないので結局できない
• ユースケースの絞り込みが重要
62
パフォーマンスとカーディナリティ
63
行キー 値 列ファミリ 列 タイム スタンプ
パフォーマンスが高い
カーディナリティが高い
行単位でのスキップが可能
ストアファイル単位でのスキップが可能
パフォーマンスとカーディナリティ
• 行キーを使うときが一番パフォーマンスが高い • 列ファミリの選択はスキャン対象のデータの数を減
らす • 値だけのフィルタはフルスキャンと同じ
• 要するに重い(ネットワーク負荷は減るかもしれないが)
64
値のシフト
• 一つのキーと値は、列ファミリー・列の名前も込みで格納されている
• だから値を列や行キーにシフトしてもデータサイズは変わらない
• 値を空にして、意味のある情報を列や行キーに含めるという手法もある
65
r1:cf1:c1:100:‘python’¥x00
r1:cf1:c1‘python’:100:¥x00
r1‘python’:cf1:c1:100:¥x00
Tall vs. Wide
66
Tall Wide
Tall vs. Wide
• Tall: 行が多く、列が少ない • Wide: 行が少なく、列が多い • Tall の特長
• Scan に向いている
• Wide の特長 • Get (特定の行のみ取得)に向いている • HBaseは行単位ならアトミックに処理可能なので、アトミッ
クな処理をしたい場合に有効
67
キー設計
68
シーケンシャルキー Saltedキー フィールド昇格キー ランダムキー
シーケンシャルリードのパフォーマンスが高い
書き込みパフォーマンスが高い
キー設計
• アクセスパターンに基づき、シーケンシャルキーかランダムキーのいずれかを選択
• 両方使う場合もある • アーキテクチャの限界を乗り越える
• どちらも使いどころを間違えなければ有用 • シーケンシャルキーにはバルクインポートを使う • ランダムアクセスをしたい場合にはランダムキーを使う
69
具体的なキー設計の手法
• リバースドメイン • com.cloudera.www, com.cloudera.blog, etc. • サイトごとの行キーが近くなる、つまりレンジスキャンがしやすくなる
• ハッシュ付与 • データをばらつかせるのに有効 • 例: MD5(逆ドメイン) + 逆ドメイン
• ソルト • 単にハッシュをとるのではなく、リージョンサーバの数で割ってmodを
とる • リージョンサーバ単位で正確に均等にしたい場合に便利
• リバースタイムスタンプ • LONG_MAX -‐ タイムスタンプ • 降順にすることで、一番最近のデータが一番上に来るようにする
70
具体的なキー設計の手法
71
元データ (ドメイン名)
リバースドメイン ハッシュ付与 ソルト
www.cloudera.com com.cloudera.www 276e_com.cloudera.www
4_com.cloudera.www
blog.cloudera.com com.cloudera.blog c75d_com.cloudera.blog 1_com.cloudera.blog
元データ (タイムスタンプ)
リバースタイムスタンプ
1358736114 2936231182
1358736150 2936231146
具体的なキー設計の手法
72
元データ (ドメイン名)
リバースドメイン ハッシュ付与 ソルト
www.cloudera.com com.cloudera.www 276e_com.cloudera.www
4_com.cloudera.www
blog.cloudera.com com.cloudera.blog c75d_com.cloudera.blog 1_com.cloudera.blog
元データ (タイムスタンプ)
リバースタイムスタンプ
1358736114 2936231182
1358736150 2936231146 ハッシュを付与することで配置を分散させる ソルトを使うことでリージョンサーバ間でより均等になる
ように分散させることも可能
具体的なキー設計の手法
73
元データ (ドメイン名)
リバースドメイン ハッシュ付与 ソルト
www.cloudera.com com.cloudera.www 276e_com.cloudera.www
4_com.cloudera.www
blog.cloudera.com com.cloudera.blog c75d_com.cloudera.blog 1_com.cloudera.blog
元データ (タイムスタンプ)
リバースタイムスタンプ
1358736114 2936231182
1358736150 2936231146
これは未ソートの状態 実際にはソートされ、元データと逆になる (新しいタイムスタンプが一番上に来る)
キー設計の例: カウンタ
• ドメイン毎、URL毎のカウンタを保存する • HBase のインクリメント(アトミックな read-‐modify-‐write )機
能を使う • それぞれの行は一つのドメインあるいはURL • 列は特定のメトリクスのカウンタ • 列ファミリは時間範囲のグループカウンタとして使う
• 列ファミリレベルでTTL(生存期間)を設定して、一定期間経過後にメトリクスが削除されるようにしてストレージ領域を節約
• 例: “Daily Counters” (日次カウンタ) 列ファミリには2週間のTTLを設定
74
キー設計の例: カウンタ
• ドメインの行キー = MD5(リバースドメイン) + リバースドメイン • 行キーを分散させ、バラバラのリージョンに配置されるよ
うにする • ロードバランシングの方法として有効
• URLの行キー = MD5(リバースドメイン) + リバースドメイン + URL ID • 行キーのサイズ節約のため、URL ID を作っておいてそれ
を使った方がいい
75
列修飾子設計 (1) 列ファミリ
• データは複数のストレージファイルに保存されることを考慮する
• 列ファミリは少なめにする • HFileの数 = リージョン * 列ファミリ * (3〜6ぐらい) • HBase は全ての HFile をオープンする • つまり列ファミリが多いと必要なファイルディスクリプタの数が
増大する • 多くても3つぐらい。1つだけで運用する場合もあり
• アクセスパターンが全く異なるデータがあるときに使うのが◯ • 例1: メタデータ + 実データ • 例2: 日次データ + 週次データ + 月次データ
76
列修飾子設計 (2) 名前
• 列ファミリ・列の名前は短い方がいい • 列修飾子全体が1行ごとに保存されるため、ここが長いと
データ量が大幅に増加する
77
列修飾子設計の例: カウンタ
• 列ファミリ • 1時間毎のカウンタ • 日次カウンタ • 総計カウンタ
• 列名は分かりやすく日本語にしているのでそのまま使わないように
78
時間毎 日次 総計
h (hourlyの略) d (dailyの略) t (totalの略)
実際にはこんな感じでいい
列修飾子設計の例: カウンタ
• 単位時間のメトリックのカウンタを配置 • <時間><メトリック>
79
時間毎 18時合計 18時東京 18時大阪 19時合計 19時東京
日次 1/1合計 1/1東京 1/1大阪 1/2合計 1/2東京
……
……
ホットスポット
• HBaseは1リージョンは1リージョンサーバが担当する • だから特定のリージョンだけにアクセスが集中する
ということがありうる(ホットスポット) • シーケンシャルキーだとホットスポットができるかも
しれない • 午前中のキーノートでもNHN Japanの中村さんがLINEでホットスポットが発生していたという事例を紹介していた • h=p://www.slideshare.net/naverjapan/storage-‐infrastructure-‐using-‐hbase-‐behind-‐line-‐messages
80
ホットスポットの例:タイムスタンプを使う
• <タイムスタンプ><他のキー>: { 列ファミリ: { 列修飾子: { タイムスタンプ : 値 }}} • これはダメな例 • ホットスポットが発生する
81
cf1 cf1:c1 cf1:c2
1358682406_metricA
1358682406_metricB
1358682407_metricA
1358682410_metricA
行キーの頭がほとんど同じ これだと、ある時間帯に1つのRSだけが
処理をすることになる
ホットスポットの例:タイムスタンプを使う
解決策1: タイムスタンプをソルトする (事前にリージョンを分割して別々のRSに割り当てておく)
82
cf1 cf1:c1 cf1:c2
0_1358682406_metricA
1_1358682200_metricA
4_1358672200_metricB
9_1358662211_metricA
ホットスポットの例:タイムスタンプを使う
解決策2: <他のキー>を前に持ってくる
83
cf1 cf1:c1 cf1:c2
metricA_1358682406
metricA_1358682407
metricA_1358682410
metricB_1358682406
例: OpenTSDB
• OpenTSDB は、メトリクスを保存するための時系列データベース • h=p://opentsdb.net/
• スキーマは以下のようになっている • メトリックの種類とタグは行キーに保存されている • 新しいタイムスタンプによる行キーは定期的に作成
• ホットスポットの解決策2の典型例
84
メトリクス(列ファミリ) <時間差分><フラグ> <時間差分><フラグ>
<メトリック><タイムスタンプ><タグ> 値 値
例: OpenTSDB
詳細は h=p://opentsdb.net/misc/opentsdb-‐hbasecon.pdf
85
+1 +2 +4
metricA_1358600000 10 12 15 metricA_1358600600 11 17 metricB_1358600000 100 105
時間の差分を列にとる 例) 1358600000 + 1 = 1358600001
一定時間ごとに新しい行を作成
86
まとめ
まとめ
• HBaseにおける正しいスキーマ設計には、ユースケースやアクセスパターンと、HBaseの内部構造を知ることが不可欠です
• 非正規化・インテリジェントキーなど、RDBと異なるテクニックを駆使することで、性能をスケールさせることができます
• 正しくスキーマを設計して、快適なHBaseライフを満喫しましょう!
87
HBase 本日本語訳出ました
• Cloudera の Lars George が書いた HBase のバイブル
• 訳は安心の玉川さん • レビュー手伝ってました
Cloudera の HBase トレーニング
HBase トレーニングではスキーマ設計もあります 今日の話だけでは物足りないという方は今すぐ登録を! 次回は3/25 -‐ 26 開催です 申し込みはこちら h=p://www.cloudera.co.jp/university/hbase.html
CDHコミュニティ・MLの紹介
CDH ユーザ メーリングリスト(日本語) cdh-‐user-‐[email protected] CDH の質問についてはこちら Cloudera ニュースレター h=p://www.cloudera.co.jp/newsle=er Cloudera に関するニュースをお届けします CDHの最新情報・使い方なども紹介します
90
宣伝
Cloudera Managerを使えば1時間でCDHクラスタの構築ができ、管理も非常に簡単です
HBaseを使うなら Cloudera Enterprise
(CDH + Cloudera Manager) を選びましょう
ダウンロードはこちら
h=p://www.cloudera.com/downloads/
91
92