大量データの書き込みに最適な『HBase』。RDBとの違いとは
「AmebaにおけるHBaseの導入事例を紹介する前に、まずはHBaseについて簡単に説明したい」──。冒頭でこう切り出したのはサイバーエージェントでHadoopを使ったログ解析基盤およびHBaseをつかった基盤システムの開発・運用を手掛けている鈴木氏である。続けて同氏は「HBaseを使ったことがある方」と参加者に問いかけた。すると手を挙げたのは2~3割。「意外に多い」と少し驚いた表情をみせ、鈴木氏はHBaseの解説を始めた。
HBaseとはNoSQLのひとつで、Google基盤ソフトウェアである『Bigtable』のオープンソースクローンである。
「一言で表すと分散ストレージ。その特徴は高可用性、高パフォーマンス。そしてデータモデルは多次元ソートマップであること」と鈴木氏。またHBaseの使いどころとして最適なのは、『大量のデータがあるとき』だという。HBaseのAuto Shardingという機能により、「データが自動的に分割され、負荷分散される。これにより、大量データに対する運用コストの削減が可能になる」(鈴木氏)という。
鈴木氏はHBaseのアーキテクチャについても次のように説明する。
「HBaseのアーキテクチャはマスタ型。HMasterとHRegionServerという2種類のプロセスがあり、マスタであるHMasterがHRegionServerの管理やコーディネーションをする」
クライアント直接やり取りするのはHRegionServerである。「HMasterに負荷が集中することがないため、HMasterがボトルネックにならない」(鈴木氏)という。そしてデータは分散ファイルシステムであるHDFS(Hadoop Distributed File System)に保存される。つまりHBaseの信頼性は、HDFSに依存しているというわけだ。
次に鈴木氏が説明したのはHBaseのデータモデルである。HBaseはテーブルのカラムにバリュー(値)を格納する、RowKey(RDBの主キー)や辞書順でソートされている点はRDBと似ているが、少し異なるところがある、と言う。それは「カラムはカラムファミリーによってグルーピングされていること、値は複数バージョン持てるところだ」と鈴木氏。そのほかにも、データ分割はRegion単位で分割されること、Rowの更新処理はアトミックに行われること、データファイル数はカラムファミリー×リージョン数となること(列指向データフォーマット)、カラムファミリーはI/Oを分割したいときに使われることも異なる点だ。またHBaseの特徴として鈴木氏は「カラムファミリーはあらかじめ定義しておくこと、カラムは後から追加できること」と挙げる。
HBaseの設計の考え方もRDBとは異なる。HBaseではRowKeyの範囲でRegionに分割されて負荷分散される。そのため、Rowkeyの設計次第で負荷やデータ量が偏ることもあるという。またRowkeyで辞書順にソートされているHBaseでは、連続したRowはScanでまとめてとることができる。したがって「一度に取りたいデータは連続して 置いておくこと」も設計する上では重要なポイントだ。そのほかにもRowのカラムはいくらでも増やすことができる、更新処理がアトミック、Joinがないので非正規化がほぼ前提となる、クエリに対してスキーマが決まる、などという点を考慮して設計をしなければならない、と指摘。「さらなる詳細を知りたい場合は、CodeZineの連載『初めてのHBase』を読んでほしい」(鈴木氏)。
Amebaのスマートフォン向けプラットフォームをHBaseで構築
事例1:『Hornet』
サイバーエージェントではどんなところにHBaseを導入し、活用しているのか。まず鈴木氏が紹介したのが、グラフDB『Hornet』の事例である。
昨年、サイバーエージェントではデカグラフ構想を基に、Amebaのスマートフォン向けプラットフォームをリリースした。デカグラフ構想とは「各サービスのユーザー層をミニグラフと位置づけ、1つの巨大なスマートフォン向けサービス(デカグラフ)を構築するというものだ」と鈴木氏は説明する。このような構想を実現するには、ユーザーのグラフ構造を保持するデータベースが必要となる。しかもそのデータは大量になるので、スケールするデータベースが必須。しかもオンライン処理をするため、低レスポンスタイム、高スループットという条件を満たさねばならない。
Ameba PiggやAmebaなう、Amebaぐるっぽでは『MySQLとSharding』を採用してきたという。しかし「書き込みがスケールしにくく、管理が大変というShardを分割してしまうと、手動でやらないといけないという問題があり、HBaseを検討した」と鈴木氏は言う。
HBaseを採用した理由は複数ある。スケールする、書き込みが早い、Range Scanができる、CASやIncrement、Auto Shardingが使えることだ。「ログ解析基盤にHadoopを用いていたため、ノウハウもあった。これは大きな理由となった」と鈴木氏は振り返る。
さらに鈴木氏はHornetのデータモデルやアーキテクチャ、スキーマ設計についても詳しく解説。データモデルについてはプロパティグラフを紹介し、各ノードのプロパティセットやリレーションの作成、隣接ノードを取得するためのJava APIなども披露。さらにはリレーションシップの追加や取得については、具体的な例を挙げてスキーマ設計を具体的に解説。前者では1が2をフォローするという例を挙げ、RowKey、ColumnKey、valueがどのようになるかを具体的に示した。また後者では『1がフォローしている人を取得』するという例を提示し、hash(1)+follow+OUTGOINGでプレフィックススキャンするというコード例を紹介した。
「今後はオープンソースで公開したい」と鈴木氏。
事例2:『Json Persister』
続いてもう1つの導入事例を紹介。それは社内ライブラリ『Json Persister』への導入事例である。
サイバーエージェントではサービスを複数ラインで同時に開発している。サービス開発においてスピードは命。サイバーエージェントでも、いかにそのスピードを上げられるかが重要な課題となっていたという。
「スピードを上げるためのアプローチはいろいろあるが、私たちが注目したのはデータベース。一部基盤化はされてはいたものの、サービスごとにデータベースを立てている状況だったからだ。そこでHBaseを採用し、すべてのサービスのデータを入れ、運用を一元化できたら良さそうだと考えた」と鈴木氏は振り返る。
とはいえ、先も説明したとおり、HBaseを扱うのは容易なことではない。そこでRDBに慣れているエンジニアにとって、いかに使いやすくするかを検討したという。
そこで着目したのが社内ライブラリ『Json Persister』だ。これはJavaオブジェクトをJsonデータとして永続化するフレームワーク。Javaオブジェクトを直接保存、ロードするシンプルなAPIとなっている。またデータストア層は切り替えられるようになっていた。もともとあったのはMySQL版。「このインターフェースに乗せれば簡単にHBaseを扱えるのではないかと考え、HBaseで実装することにした」という。
具体的にどのように実装したのか。鈴木氏はスキーマ設計の詳細を披露した。RowKeyはインデックス名+インデックス値+主キーとし、カラムファミリーは"h"、カラムは使わないので空のバイト配列、そしてvalueはJson。
例えば『yusaku』という32歳の新規ユーザーを追加する際のコードは、次のようになる。
UserData userData=new UserData(); userData.setUserName(”yusaku"); userData.setAge(32); userData.setDate(new Date()); jsonPersister.save(userData);
このほかにも主キーで取得(load)、RowKeyがAge+32でプレフィックススキャンするというリストを取得するコード例なども紹介した。これについても「今後はオープンソースで公開したい」と鈴木氏は言う。
「今日の講演を聴いて関心をもたれた方は、ぜひ一度HBaseに触れてもらいたい。そしてHBase仲間になってほしい」
最後に鈴木氏は参加者にこう呼びかけ、セッションを締めくくった。