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はカラム指向のデータベースと呼ばれますがデータモデルは多次元ソートマップです。
図解すると下記のような感じ。
RowKey1 | ColumnFamily1 | ColumnFamily2 | |||||
ColumnQualifier1 | ColumnQualifier2 | ... | |||||
Value1 | Version1 | Value2 | Version1 | ... | |||
... | ... | ... | ... | ... | |||
RowKey2 | ... |
Javaでいうと
Map<RowKey, Map<ColumnFamily, Map<ColumnQualifier, Map<Version, Value>>>>
という感じ。
Map
Map
テーブルは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を設計しているようです。