今回は構築・運用中のログ解析基盤「Patriot」について書きたいと思います。
Webサービスを運営していると日々大量のログデータやユーザデータが蓄積されます。
今まではPV(ページビュー)やUU(ユニークユーザ)などアクセスログなどから取れる、大枠の指標のみを見ることがほとんどでした。
ページビューに合わせてシステムを増強するなど、システム側としては十分とも言える指標ですが、広告や課金サービスという視点から見ると十分とは言えません。
今まではAmeba内の個々のサービス担当者が必要とする指標を出すためにアプリエンジニアやDBエンジニアに都度依頼をする形でデータを抽出していました。
今後の課金サービスの発展が見込まれ、よりデータ分析の重要性が高まると考えた私は、エンジニアでないサービス担当者(主にプロデューサ)がより簡単に、より細かくサービス指標を見ていけるようにするための基盤づくりを今年から(本格的には3月末から)始めました。
まず考えたのは大量のデータをどう扱うかです。
これは社内にもある程度ノウハウがあること、昨年の11月に開催された「Hadoop Conference Japan 2009」に参加した際に、Hadoop関連プロダクトが整備されてきていることを知ったことなどからHadoopを利用する方針に決めました。
http://hadoop.apache.org/
http://www.cloudera.com/
分散ファイルシステムのHDFS、Map/Reduceなど大量データを扱うのに非常に適していますし、(各種資料から)「基本的にはデータの容量だけを考えてサーバ構成を見積もれば良い」のでシステム設計しやすいことも理由の1つです。
http://www.cloudera.com/blog/2010/03/clouderas-support-team-shares-some-basic-hardware-recommendations/
次にログファイルの扱い方とそれをどう解析するかです。
まず概念としてログを2種類に分類しました。ユーザのアクセスを記録している「アクセスログ」(Apache HTTP Serverログなど)とユーザの行動を記録している「行動ログ」(APサーバから出力されることが多い。たとえば「ログイン」、「アイテム購入」などを示すログ)です。
直近で必要としているのは課金系サービスの解析ですので、どういうユーザ行動が課金に結びつくのかなどの解析を想定し、行動ログを収集することから始めました(ゆくゆくはアクセスログからの解析も進めていく予定です)。
ログファイルは出力項目などほぼ固定ですので半構造化されたデータと言えます。これを扱いやすいように構造化したいところです。
またHadoopによる大量データ解析ではJavaでMap/Reduceプログラムを書くことになるのですが、これが大変です(私は未だに上手く書けません)。
そこで登場するのがHiveです。
http://hadoop.apache.org/hive/
Hiveはデータを構造化し、SQLライクな言語(HiveQL)でデータを扱えるようにすることができます。
半構造化されたテキストファイルをタブ区切り、カンマ区切り、正規表現でのグルーピングなどを組み合わせてカラムに分け、テーブル名、カラム名で扱えるようにできます。
これらのテーブル定義情報はメタストアに保存されます。メタストアには組み込みDBやMySQLなどが利用できます。
同様の試みとしてPigがあります。HiveがFacebookで開発されていたのに対して、PigはYahoo!で開発されていました(今は共にHadoopのサブプロジェクトです)。
Pigも検討しましたが、SQLライクな言語であるという点、簡単なJOINの速度検証でMap/Reduceを生で書いた場合と遜色ない速度であったことなどからもHiveを選択しました(その後、Pigも開発が進み、その速度差は小さくなっているようです)。
ハードウェア選定ですが、前述したとおりデータ容量にのみ依存し、同じ構成のサーバを複数台並べていく方針でいきます。
当時のアクセスログの容量などから少なくとも1年分はもつ程度(危なくなったら増やしますという了解のもと)ということで1TBのHDDを4台、メモリ16GBを積んだ1Uサーバ18台と別にマスターサーバ(NameNode、JobTracker)として2台(1台はSecondary NameNode)の計20台のクラスタを構築しました。
HadoopはClouderaが提供しているCloudera’s Distribution for Hadoop (CDH)を使用しています。現在はヴァージョン3にあたるCDH3を使用しています。
Hiveの便利なところにパーティションが使えるということが挙げられます。
ログはDailyや量によってはHourlyでローテートすることが多いですが、パーティションを使用すると
INSERT OVERWRITE TABLE
test_part PARTITION(ds='2010-03-10', hr=12)
SELECT * from t;
というように、簡単に日付ごと、時間ごとに分けることができます。
http://www.cloudera.com/blog/2010/07/whats-new-in-cdh3b2-hue/
決まった解析をDailyやMonthlyで行う場合はスケジューリングしてHiveジョブを実行し、その結果をサマリデータベース(MySQLを使用しています)に入れ、Web UIからグラフ表示するなどしていつでも確認できるようにしています。
また、細かな条件を組み合わせたデータ抽出は都度Web UIから実行できるようにしています。
今のところプロデューサなどから要望のあった条件設定項目を入れていますが、今後サービスの増加などで項目が増えることが予想され、項目追加依頼に対応できなくなる可能性があるので、Hiveクエリを直接Web UIで書くことができるHUEを導入しようと考えています。
解析するプロデューサにSQLを書いてもらうことになりますが、雛形を保存する機能もありますし、多少のSQLは是非ともプロデューサの皆様にも書けるようになっていただきたいということで導入の方向で進めています。
現状ではログの容量もそこまで多くはなく、一般的なRDBでも良いだろうと思われる部分もありますが、データ量増大による先々の不安がないこと、データ量増加でクエリ実行速度の劣化が少ないなどのメリットを考えると、この構成は妥当でしょう。
今後はスケジューリング・ワークフローシステムの自作もしくはOozieの使用、ログ収集にScribeやFlumeの使用も検討しています。
http://www.cloudera.com/blog/2010/07/whats-new-in-cdh3-b2-oozie/
http://github.com/facebook/scribe
http://www.cloudera.com/blog/2010/07/whats-new-in-cdh3b2-flume/
データが集まり、解析の基盤ができればあとは好きなように解析できるので、今後面白い解析ができればなぁと思っています。
また、サービス提供をした際のユーザ行動をセンシングしてユーザをモデル化し、そこから得られたものをサービスにフィードバックするというサイクル(しかも短期間のサイクル)を作っていければと思っています。