読者です 読者をやめる 読者になる 読者になる

第8回データマイニング+WEB勉強会@東京で発表してきました。「MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析」

勉強会 MongoDB GraphDB

お久しぶりです。@です。11/14(日)に行われました、第8回 データマイニング+WEB 勉強会@東京−大規模解析・ウェブ・クオンツ 祭り−で発表してきました。Togetterも参考にして下さい。

発表者・参加者双方の議論を重視するこの勉強会、今回もアツイ議論が絶えず巻起こって、とてもエキサイティングで有意義な勉強会でした。僕は前回に引き続き、今回も発表側として参加させていただきました。その時の資料は以下になります。

前回のログ解析バックエンドの続編として、散在する各種ログを集計してMongoDBに入っているデータを表・グラフとして可視化するためのフロントエンドのお話と、ソーシャルデータの解析をGraphDBであるNeo4jを用いて解析した事例を紹介させていただきました。解析方法の詳細はスライドの方に盛り込ませて頂いたので、今回は今までの解析の総括として以下のアジェンダでお話させていただきます:

  1. 解析用DBとしてのMongoDBの役割とそのメリット
  2. 3ヶ月の仕事を通して感じたこと

GraphDBに関しては次のエントリーでがっつりと書ける程のネタがありますので今回はスルーさせていただきます。

解析用DBとしてのMongoDBの役割とそのメリット

発表や懇親会で「なぜ解析用のDBにMongoDBを選んだのか?」という質問をいつも頂きます。今までのエントリーなどでもその理由をちょくちょく書いてきましたが、今回改めて書こうと思います。まず結論として、MongoDBを採用して間違いなかったことを確信しています。もしこれで無ければもっと基盤構築に時間がかかっていたでしょうし、もっとごちゃごちゃした構成になっていたと思います。といってもそれは作業者のスキル・サービス規模・社内環境/風土・リソース…といった様々な制約条件によって変わってくるものであると思います。なので僕はどのような制約条件の元で仕事をしているか、そこからお話をさせていただきます。
ここでは「データ」を様々なログの1つのレコード、あるいはそれを軽く集計した形でMongoDBに格納されたものと定義します。対して「指標」とはその(複数の)データから計算された最終出力としての数値と定義しておきます。

解析環境・ノウハウ、何も無いところからスタートした(ただ、ログはきちんと残しておいてくれていた)

もともと解析環境やノウハウが無いところからスタートしました。ソーシャルアプリの「おみせやさん」が大ヒットして、弊社が「お客さんにもっとこのゲームを楽しんでもらいたい」→「そのためにログ解析をきちんとやって科学的に仮説検証・実行していこう」というフェーズにあったところに僕が運良くジョインさせてもらったというのがそもそもの流れです。ちょうど8月のことです。ですのでこの課題のゴールとしては、

「とにかく色んなデータを採って検証してみたい」

という、なかなかふわっとしたものになります。例えば他のゴールとしては「PV、UU、ARPU…といった決められた基本指標を出して欲しい」といった場合もあると思います。数TBの手に負えない規模のログデータを持っていたり、そこまで解析を重視しない(そんな余裕がない)といった状況では、基本的な指標算出のみにとどまるでしょう。そういった取るべき指標が明確に決まっている場合はまた違った、もっと効率的な解析手法があったと思います。僕の場合はとにかく色んなデータを採取して見る必要がありましたので、まずログの情報がほとんど”生”の状態で保管しておく必要がありました。まずはどんなデータがあって、どんな数値・特性を持っているのか、そしてそれが今後の意思決定に必要なものになりうるか取捨選択、ということを解析者である僕自身が細かく確認していく作業をしていかないといけません。ですので、

「解析者が必要な時に必要なデータを簡単に眺められて、その特性を見れる」

環境が必要でした。これは、

  • 常にデータが手元にある(社内から簡単にアクセスできる)
  • 散在するログから抽出したデータは一つの場所に集約しておく
  • データの特質を簡単に確認できるデータ保存方法である

ようにしなければならないという事です。今採れているおみせやさんのログは4種類、

  1. MySQLに入っているユーザーの登録情報、課金情報
  2. Cassandraに入っているユーザーのゲームステータス
  3. AmazonS3にバックアップされているゲームのアクセスログ
  4. AmazonS3にバックアップされているユーザーの行動ログ

で、これらを社内から解析者が簡単にアクセスできる1つの場所に集約しておく必要がありました。MySQLのデータは解析専用のレプリケーションを作って頂いて社内からアクセスできる状況にしてもらいました。Cassandraのデータは可動サーバー上にデータを取得するPHPスクリプトを書いて置いておき、社内からそのPHPを叩いてデータを引っ張ってくるAPIの形で取得するようにしました。(実はここはThrift+PHPの形から、Pigを用いてより効率よく取得していく形を考えて実装しようとしています。ですので資料内のバックエンドの構成図では「Cassandra」→「Hadoop」→「MongoDB」の流れになっています…)残りの行動ログ、アクセスログはS3とデータ同期する社内データストレージを構成して、社内から簡単にアクセスできるようになっています。

これは今から考えるとなかなか難しい要請であったと思います。MySQLやCassandraに関しては、そもそもアクセスする権限を解析者に与えてくれること・整備されたネットワーク環境・それなりの規模であったからそれができたのであり、ファイル形式のログも、今まで全てをきちんとS3にバックアップしてくれていたこと・それを社内で同期できる程のデータ量・ネットワーク環境・リソースがあったからこそです。そして何よりもインフラエンジニアの快い協力があったからです。今回は社内にデータ解析サーバーを構成していますが、例えばサービスを全てAmazonEC2上で構成していれば、解析サーバーも手法も全てAmazonEC2・S3上に集約して解析していたと思います。そうなればもっとAmazonクラウド上でのメリット・デメリットを考慮した構成になっていたと思います。MongoDBも使っていなかったかもしれません。

次は集約してきた各種ログをどのような形で保管していくかの問題になります。それぞれファイルの形で管理しておくことも考えましたし、MySQLで管理、Hadoopを活用して(HIVE、Pig、HBase)HDFS上で管理することも考えました。その中でなぜNoSQLのMongoDBで管理するようになったのかというと、

(管理上の理由)

  • スキーマレスであったこと
  • 他のサービスのログに対しても1つの解析基盤で管理する
  • もっともわかりやすくシンプルで管理しやすい方法であったこと

(後の処理を考慮しての理由)

  • 他の解析者が裏側の構成を把握しなくてもデータをとってくることができる
  • 色んな検索条件でデータを引っ張ってこれること
  • データ増大に備えてスケールしやすいものであること

などが挙げられます。まず初めの2項目、

  • スキーマレスであること
  • 他のサービスのログに対しても1つの解析基盤で管理する

ですが、これはログの情報をできるだけ落とさずに保管しておきかったのと、そもそも1つの行動ログの中でも項目全てが統一された形式で記録されていなかったことが原因になります。さらに今後のイベントや解析手法確立、新サービスリリースなどによってログの項目、とり方が増えたり変わったりする可能性が大きくあることを考慮しての事です。全てのデータにスキーマを定義するのはそもそもデータの種類や性質を把握することから始める時点で困難でありましたし、何かあるたびにスキーマに頭を悩ますのを避けたかったというのもあります。

  • もっともわかりやすくシンプルで管理しやすい方法であったこと

これは結構大きな理由です。なにせ僕ひとりで全ての解析をバックからフロントまでを管理しないといけない、そして僕は駆け出しのへっぽこエンジニアかつアルバイトの身ですのでできるだけシンプルでわかりやすく、かつ特にバックエンドの構成に関しては一度構築したあとはできるだけ手を加えることのない、また僕がいなくても他のエンジニアが構成を容易に把握できて、何かあったときには対策を替わりにしてもらえるようなものにしたかったからです。

  • 他の解析者が裏側の構成を把握しなくてもデータをとってくることができる
  • 色んな検索条件でデータを引っ張ってこれること

これは実際に様々な軸で解析を行うときにどれだけそれがやりやすいか、という次のステップでの処理を考慮した話です。もし今後、解析者が入ってこられるとしたならば、いつでも欲しいデータにアクセスできるという前提のもとで解析自身に専念して欲しいという想いがありました。そもそも純粋な解析者でバックエンドの作業が好きな人はいませんでしょうし、もっとも経営クリティカルなのはデータから何を導き出すかですので、今後増員を考えるならフロントよりの方を集めて欲しいという考えもありました。そういうところではファイルとしての管理方法よりも、DBの一つの大きなストレージの中で管理しておき、かつHadoopなどの特別な知識がなくても、簡単な検索クエリーで好きにデータをとってこれるものが望ましかったです。最後に

  • データ増大に備えてスケールしやすいものであること

これも重要ですね。サービスは今後絶対に増えていきますし、それに伴ってデータは増えていきます。データ量が10倍になることもありうると考えると、今から簡単にスケールする仕組みを考えておかなければなりません。

MongoDBの何が嬉しいのか

上のような環境や想定を踏まえて選択したのがMongoDBでした。ではなぜMongoDBかというとその性質

  • スキーマレスであったこと
  • ドキュメント志向であったこと
  • クエリの種類が非常に豊富であったこと
  • 更新性能より検索性能が優れていること
  • (Replication、Shardingの2つの観点で)スケールしやすいこと
  • コンソール上で簡単にデータ操作ができ、かつユーザー定義関数が作れること
  • Pythonなどの各種言語のドライバが整備されていたこと
  • ORM、REST Interface、node.jsに対応するドライバも整備されていたこと

であったからです。

  • ドキュメント志向であったこと

は人に読みやすい形式JSONでレコードを眺められるからです。なにせ格納されているデータの種類や特性を把握しないといけないので、その度に何らか人が読める形に整形して出力するのは効率が悪かったからです。また、フロント側のWebUIにはjQueryを使ってテーブル作成やグラフ描画を考えていました。そこにはJSONの形式で投げるので、もともとJSON(内部的にはBSON)の形式でデータを持っていれば、データを取り出して可視化するまでの処理が非常にシームレスです。

  • クエリの種類が非常に豊富であったこと
  • 更新性能より検索性能が優れていること

これは非常に重要な要素でした。解析は様々な角度から多角的に行う必要があります。そういった用途では時間による範囲検索や、特定の項目での絞り込み、や複数条件での検索、集約関数の充実などの機能が備わっていないといけません。かつ、高速に検索できるよう、インデックス機能を備えているかも重要になります。たいていのNoSQLではSQLでは当然だったクエリの種類が少なかったり、そもそも各所にインデックスを貼れることもできないものが多いです。逆にその部分を犠牲にして更新機能などの他の機能を充実させています。MongoDBは更新機能はそこそこですが、検索クエリがずば抜けて豊富で全ての項目にインデックスを作成することができます。これは解析用のDBとしては非常にありがたいことです。

  • (Replication、Shardingの2つの観点で)スケールしやすいこと

MongoDBの一つの大きなウリはスケールアウトが容易なことにあります。Replicationに関してはReplica setを構成すれば3台以上ののサーバーでデータを同期でき、かつMasterに障害があった場合でも自動的に次のMasterを昇格してくれるフェイルオーバー機能を備えています。Shardingに関してはオートSharding機能があり、指定したキーに対して分散したサーバーに自動的にデータを振り分けてくれます。しかもこれらの機能を非常は簡単に扱うことができます。

  • コンソール上で簡単にデータ操作ができ、かつユーザー定義関数が作れること

MongoDBはコンソール上でデータの操作が簡単にできます。かつコマンドはJavaScriptで書かれていて、独自の定義関数をJavaScriptで書けばそれが使えるようになります。例えば毎回実行するけれども、長くなってしまうようなコマンドはこのユーザー定義関数にしておけば非常に楽です。また、コンソールで色んな操作ができることは作業効率の大幅なアップにつながります。

  • ORM、REST Interface、node.jsに対応するドライバも整備されていたこと

これは後のフロント側の処理に関連するところです。WebUIではMongoDBに入っているデータを取得→可視化しないといけませんので、そのための何らかのドライバが必要です。MongoDBはそのための豊富なドライバが各種言語で用意されています。

以上を見ると、MongoDBは今回の僕の解析に求められる条件をほとんど満たしていることがわかります。他の方法ではここまで条件を満たしてはいません。HBaseやCassandraはそこまで検索クエリが備わっていませんし、HiveやPigはデータの可視性や操作性などで面倒な部分があります。CouchDBやRiakなどの他のドキュメント志向DBと比べましても検索クエリが一番豊富でありますし、各種ドライバも豊富です。かつ大容量のレコードを扱えるGridFSやパフォーマンスの非常に高いCappedCollectionといった独自の便利な機能は後に使用することになりそうだとも考えていました。それでは逆にMongoDBの弱点を挙げてみますと、

  • Replicationが遅い
  • メモリ・HDDを大量に消費する
  • インデックスがメモリに乗らなくなった時点でパフォーマンスが著しく低下する
  • 管理者向け機能がプアである
  • map/reduceがシングルスレッドで行われるため、その間DBがロックされる

ことが挙げられますが、これらは解析用として使うにはそれ程クリティカルな要素ではありません。瞬時に大量の書き込みを絶対に裁かないといけないワケでもありませんし、社内向けDBなのでオープンにする必要もありませんし、基本的に毎日1回のバッチ処理ですので速度が多少遅くても問題ありません。メモリやHDDも急激に消耗することも少ないですので、ある程度事前に対策ができます。Shardingも簡単にできますからね。

技術は適材適所、その場に応じたものを選択することが重要

MongoDBを採用した理由はだいたいこんなところです。今回の自分の制約条件を満足する最も最適な解がMongoDBだったのです。前述しましたように条件が変われば解はいくらでも変わってきます。大事なことはその条件に応じて常に最適な技術を選んでこれる能力だと思っています。ただ、プロバイダー側のソーシャルアプリのログ解析においてはだいたい同じようなことが当てはまるような気がします。もし似た環境におられる方は、一度MongoDBを検討してみては良いかと思います。あと、一つの技術だけで全ての要請を満たすことはできないとも感じています。今回の資料にもありますが、ソーシャルデータの解析にはGraphDBを用いた方が便利なような気がします。GraphDBの中でNeo4jはその中で最も発達したDBで、かつ今まで使用してきたPythonのドライバがあって、REST Interfaceも備えています。そういったMongoDBと共通に扱える要素が多いという意味でMongoDBとGraphDBを現在は共存させています。

3ヶ月の仕事を通して感じたこと

芸者東京エンターテインメントにアルバイトに入って、ゼロからログ解析を初めて早くも3ヶ月が経ちました。今少し感じていることを書いてみます。

解析という仕事にはバックエンドとフロントエンドの2種類があって、求められる技術が全く異なる

今までのおはなしの中でもわかって頂けると思いますが、解析という仕事は大きく2つに分類できます。1つは散在するログを集積し、何らかの形式で保管・管理するための仕組み(基盤)を作るバックエンドの部分と、もう1つは欲しいデータが常に手に入るという前提の下でRやEXCELなどのツールを駆使して実際の解析を行ない、経営や企画の意思決定に貢献する部分です。前者で重要なのは、インフラやDBの知識、あるいはHadoopやNoSQLなどの大規模データ処理技術を使いこなせる能力や各種制約の下で適切なアーキテクチャを構築できる能力で、逆に前者はユーザー支点や多角的に物事を観察できる能力、各種ツールを使いこなせる能力です。ですので解析者がいない企業では、前者はインフラエンジニアが兼任し、後者はマーケティング担当や企画側が兼任することになると思います。もちろんどちらの知識も併せ持つことが重要ですが、もし解析者としてエキスパートになるのならば、どちらの方でそれを目指すのかということを考えていかないといけないかもしれません。解析者というと後者の方をイメージされる方、目指している方が多いかもしれません。僕は前者のバックエンドのほうでエキスパートを目指していきたいなと思っています。そこら辺の話はまた別の機会にしたいなと思っています。

とにかく今回の勉強会もとても有意義な素晴らしいものでした。運営者のみなさん、会場を貸していただいたニフティのみなさん、参加されたみなさん、本当にありがとうございました。今後とも宜しくお願いします。