HBaseのRow Keyの設計についてのメモ

Facebook Messageで使われたりLINEのストレージで使われたり、と事例も多く出てきているHBase(Bは大文字。これ重要)ですが、個人的に少し興味も湧いてきたのでちょっと調べてます。HBaseはLog-Structured Merge-tree (LSM-tree)というアーキテクチャを使っており大量データの書き込みに最適化されています。なので大量の書き込みがあり読み込みは直近のもののみというメッセージ系アプリに向いているんだと思います。


そういえば半額に釣られてManning | HBase in Actionも買ってしまいました。
この本の4章のRow Keyの設計についての話があってそれがちょっと面白かったので関連してRow Keyについて少し書いてみます。


まずHBaseはカラム指向のデータベースと呼ばれますがデータモデルは多次元ソートマップです。
図解すると下記のような感じ。

RowKey1ColumnFamily1ColumnFamily2
ColumnQualifier1ColumnQualifier2...
Value1Version1Value2Version1...
...............
RowKey2...


Javaでいうと

Map<RowKey, Map<ColumnFamily, Map<ColumnQualifier, Map<Version, Value>>>>

という感じ。


MapValueはカラムの値です。上記の表の例でいうとValue1ですね。
MapのVersionはカラムのバージョンです。カラムの値は複数のバージョンを持つことができます。上記の表の例でいうとVersion1ですね。


テーブルはColumn Family毎に管理されます。これがカラム指向のデータベースと呼ばれるゆえんです。
データはRegion単位で分割されます。またデータはRow Keyでソートされます。各RegionはRegionServerで管理されます。この辺は下記プレゼン資料がわかりやすいです。



HBaseにおいてはRow Keyの設計は重要です。なぜならRow Keyの値がそのままデータの物理的な配置に影響するからです。
例えばタイムスタンプのように単調増加するものをそのままRow Keyに設定した場合は最後尾のRegionに書き込み負荷が集中してしまいます。RDBMSのprimary keyとの違いはここです。RDBMSの場合はprimary keyが物理的な配置に影響することはありません。

ただかといって完全にランダムにやってしまうと読み込みが遅くなる可能性があります。
なので例えばクロールして収集したURLをRow Keyにする場合は逆に表示させると良いようです。

つまり

Row Key
images.google.com
...
maps.google.com
...
www.google.com

ではなく

Row Key
com.google.images
com.google.maps
com.google.ww
...

にします。
こうすれば同じドメインのデータを処理するときに同一Regionになり処理が効率的になります。

なおこの例はGoogleを支える技術 ?巨大システムの内側の世界 (WEB+DB PRESSプラスシリーズ)から取りました。


HBase in Actionの4章ではTwitterのようなつぶやきサービスを作るときのRow Keyの設計について考察がされています。

例えばフォローしている、されているの関係を表現する場合はRow Keyをどう設計するのがいいのか?みたいなことが書かれています。興味ある人は見てみるといいかも。


ちなみにFacebook Messageの検索

では下記のようにRow Keyを設計しているようです。