解析者として僕が大事にしていること
あけましておめでとうございます。@doryokujinです。今回は技術的な内容ではなく、フロントの解析者・アナリストとして僕が大事にしていること・日々感じていることを書きたいと思います。
このエントリーのきっかけは、最近多くの方から以前の10月に書いたエントリー「解析者の立ち位置」について僕が思うこと。に対して多くの共感のコメントを頂いた事です。この事で僕は今年も解析者として変わらぬ信念を持って、今いっそうの努力を続けていけばよいのだ、やるしかないという決意をもつことができました。コメントを寄せて頂いた皆さん、どうもありがとうございました。
解析者として僕が大事にしていること
ここ数年においては、データが大量に蓄積されてきており、それを解析・マイニングするデータ解析者の重要性が理解されるようになってきているように感じています。それは解析者にとって非常に喜ばしいことでもあると同時に、大きなプレッシャーにもなっているような気がします。
そのプレッシャーの1つに、企画者や経営者・あるいは顧客といった結果を活用する人々(=意志決定者)の「これだけ材料(データ)が揃っているのだから多くの課題が解決できるはずだ」という期待に応えないといけないというプレッシャーがあると思います。しかし正直なところ、いくら大量のデータが揃っていたとしても経営が一気に改善できるようなエクセレントな結果をすぐにもたらすのは非常に難しいと思っています。逆にデータ量が増えて様々な要因が複雑に絡みあって何も見えてこない状況に陥ることもあります。
もちろん僕たち解析者の使命は「データから経営クリティカルな結果をもたらし続けること」であるのでこの困難さから目を背けるわけにはいきません。今日はそんな状況の中で解析者は日々どういう立ち位置で、どういう結果を出していけば良いのかについて僕が大切にしている事を4つお話したいと思います。
- 「当たり前の結果」をたくさん出す事の大切さ
- 誰のために・何のために解析をやるのかを意識する大切さ
- 1人で全部背負わない事の大切さ
- 自分の存在価値を高めるための活動の大切さ
1. 「当たり前の結果」をたくさん出す事の大切さ
僕は解析において「当たり前の事をきっちりやる・当たり前の結果をたくさん出す」事は非常に重要な事だと感じています。ただし解析者という専門的な立場である以上、「何も有意な結果が出てこなかった」「当たり前の結果しか出てこなかった」というわけにはいきません。中には常に「何か新しい発見をしないといけない」という焦燥感にとらわれながら仕事をしている人もいるかもしれません。
しかし僕は「意味のある・新しい発見」をもたらすためには「当たり前の結果」を積み重ねることが大前提で、その事をもっと意識して解析をすることがとても重要だと考えています。
その当たり前は本当に当たり前なのか
そもそも「当たり前の結果」というのは誰にとって当たり前なのでしょうか?僕たち解析者の考える当たり前と、意志決定者の考える当たり前は本当に同じなのでしょうか?僕の経験から思うことは「解析者の考える当たり前の半分は意志決定者にとって当たり前ではなく、またその逆もしかり」という事です。
当たり前と思っていた結果を渋々見せると「へぇ、意外に××なんだ、面白い」という反応が返ってきたり、逆に新しい結果が出たと思って見せると「やっぱり」「そりゃそうだよ」といった反応が返ってくることは実は良くあります。つまり解析者がたいした事の無いと思っている結果が実は意志決定者にはとても貴重な情報となる事が多数あるということです。しかし実際は解析者はそういった結果を出す事に注目を置いていないために、多くの意志決定者にとって重要な結果があまりもたされないといった現状に陥ってしまいがちです。
だから僕は「当たり前の結果をたくさん出していこう」という意識を強く持つことはとても重要なことだと思っています。具体的にどうするかというと、できるだけたくさんのデータを出してあげること、しかもわかりやすい表やグラフの形でたくさん出してあげることだと思います。そして何度もその共有を意志決定者と繰り返す。その共有を繰り返すことで相手が何を求めているのか、どういう結果に意味のあるのかがだんだん見えてくると思います。それこそが意味のある有意な結果をもたらす第一歩になると思います。
本当に当たり前の結果を与えることも実は大切
しかし、本当に当たり前の結果、意志決定者が「やっぱりそうか」という結果には意味が無いといえば、決してそんな事はありません。意志決定者が頭の中で感じている事を数値やグラフで裏付けてやるという事はとてもとても意味のあることです。自分の考えている事の正しさがきっちりと検証される事によって得られる安心感と自信は想像以上に大きなものです、そしてそれが次の意志決定の確信度をどんどん高めていきます。相手に安心感を与えてあげるのも僕たちの大きな仕事だと感じています。
「当たり前の繰り返し」が新しい発見を生み出す
「意味のある結果を出さないといけない」という事に執着しすぎに、もっと当たり前の事: " たくさんデータを提示してたくさん表作ってグラフ描く、そしてそれを何度も相手と共有する " 、そういったことをきっちりとこなすことは解析者にとって非常に重要な仕事だと思います。難しいことをやろうとして頭を悩まし、手を止めるよりは、どんどんデータをわかりやすい形で提示して行く方が有意義だと思いませんか?そして結局のところ、新しい発見や経営クリティカルな結果というのはそういった事の繰り返しの上に生まれてくるものでは無いでしょうか?
2. 誰のために・何のために解析をやるのかを意識する大切さ
これは以前のエントリーの中心部分になるのでかぶるのですが、そもそも誰の・何のために解析をするのかという意識を常に明確にしておくことはとても重要だと思っています。
人間の意志決定を支援するために解析をすること・解析結果自身が意志決定を行うのではないこと
解析者は「人間の意志決定を支援するための結果をもたらすことに注力する」という意識を持つ、そのために「難しい事はしない、いかにわかりやすく・簡単に結果を人に提示できるかを意識する」事はとても重要だと思っています。
逆に解析結果自身が意志決定を行う場合というのは、例えば「リコメンドエンジン」や「需要予測システム」を作る場合でしょうか。機械学習や統計モデルといった高度な手法を駆使して、データから機械的に最適な解をもたらし、それを元に自動的にサービスに適用していく。その人の過去の行動から自動的に趣向を理解して適切な商品を推薦する、過去の大量の販売履歴からどれくらいの需要があるのかを数値で提示するといったものです。こういった瞬時に結果を出さないといけない状況や人間の手に負えない状況においては非常に重要です。
しかしそういった目的では無い場合、単にデータを解析する場合においては、解析を「人間の意志決定を支援する」ために注力して行う事が重要だと思います。
そのためには難しい解析手法を用いる必要はありません。例え複雑なモデル式を作ったり、 " 課金額687.3円〜3456.7円・プレイ期間3.4日〜8.9日のユーザークラスタの分布 " といった微妙な境界をもったクラスタリングをしても、それを知った所で人間がどういう意志決定ができるでしょうか?逆に多少誤差があっても、クラスタに偏りがあっても、できるだけ線型モデルや " 課金額1000円〜5000円・プレイ期間1日〜7日のユーザーの分布・傾向 " といったわかりやすい結果で提示してあげることの方が相手にとって意味のあることのように思います。そしてそれをちゃんと可視化してあげて、どれくらい誤差があるのか分布に偏りがあるのかも含めて伝えることも重要です。
解析手法に対するこだわりを捨てること
今まで大学の研究などで非常に高度で複雑な解析手法を用いてすごい事をやってきたという人も多いと思います。機械学習によって自動的に意志決定が行われるということに非常に喜びと価値を感じている人も多いと思います。あるいはそういう高度な知識をアピールする事で周囲に自分の業務の理解や専門性を訴えたくなるとも思います。
そういった人達はどうしてもそういった高度な手法を使いたくなると思いますし、その気持ちはとてもとても理解できます。しかし新しい事をしてジャーナルに掲載されるための研究や、リコメンドや予測といったデータ解析とは違った目的で使用される機械学習、自分の評価のために無駄に複雑なことに時間とお金を費やす行動は、データ解析における目的とは全く異なるものです。
こだわりを捨て明確な目的意識をもって、人間の意志決定を支援するための結果を出す・そのためにどうしたら良いか・どう分かりやすく伝えたらよいか、を必死で考えていくことの方が非常に重要な事のように感じます。
※(追記)もちろん、会社の規模やフェーズなどによっては高度な解析手法や基盤技術を生み出す事もとても重要な解析者の仕事だと思います。
3. 1人で全部背負わない事の大切さ
解析者がデータを集めてきて解析して結果を出す、その事を全て1人で背負う事は非常にしんどいことであり、あまり良くないことだと感じています。初めは僕も「全てを自分でやってどんどん良い結果を提示していかないといけない」と意気込んでいましたが、その困難さに気付くようになりました。
日々増え続け・変わり続けるサービスの全てを把握するのは困難
解析者は自社・あるいは顧客先のたくさんのサービスの解析を一手に引き受けなくてはなりません。そしてWebサービスにおいては非常に早いペースでサービスがリリースされ・絶えず変更されていきます。サービスの全ての内容・特徴・構造、またはログ周りに関するプログラム・データベースのテーブル構造を全てのサービスで把握して解析を行うことは実質不可能です。それにも関わらず全部1人で背負うのは心身共にしんどい事です。
最も優秀な解析者になり得るのは実はサービスを作った人である
これも経験から感じている事ですが、いくら解析の専門技術を持っていたとしても、実際にサービスを作った人の持つ仮説検証能力やデータの読み取り能力には敵わないことが多々あります。そこで「サービスを作った人にも解析に協力してもらう」、「彼らにはない、より科学的な見地で解析を行う」ことが負担を減らす意味でも、良い解析をする意味でも非常に重要なことだと思います。
エンジニアにももっと協力してもらう
一方で解析の元となるログを出してくれるのはインフラエンジニア・アプリケーションエンジニアの人達です。ログのレコードの意味がわからない事や、取得して欲しい項目がある事は日常良くあることです。また、データベースのどのテーブルにどういう形でデータが記録されているのかも全て把握するのは困難です。そしてこれらを自分で頑張って追っていくのは時間の無駄です。そいういう部分は割り切ってどんどんエンジニアに聞く方がよいと思っています。
相手の手をわずらわせないために、どういうデータが見たいのか、あるいはどういう目的で新たな項目を記録して欲しいのかをわかりやすく伝える努力はとても重要です。
4. 自分の存在価値を高めるための活動の大切さ
解析者という業種は環境に依存するところが大きいです。大きなサービスがあるからそこに大きなデータがあり・解析需要が生まれてきます。また、IT産業が拡大し続けているからこそ「データ解析してみよう」という余裕が生まれ、開発者や企画者(=サービスを生む人)以外に解析する人を雇用しようとします。それは現実として会社が傾けばまず解析者の存在が危うくなり、IT産業自身が傾けば市場価値は下がっていく傾向をもたしています。
しかし本当にそれで良いのでしょうか?逆に経営がピンチな時ほど、産業が衰退していく時こそきっちりとデータに基づいた戦略・下支えが必要では無いのでしょうか?悪い原因を一つ一つ地道に突き止めて行き改善していく、そういった事こそが何より重要だと解析者の皆さん自身が一番感じているのでは無いでしょうか?
勉強会など、社外に向けて発信していくことの重要性
だからこそ自分の存在価値を認めてもらうための活動はとても重要だと思います。それを通じて良き理解者や同業種の仲間を増やして行きます。
社内においては結果を出すことに併せて、エンジニアや企画者・経営者と積極的にコミュニケーションをとって解析の良き理解者になってもらうことでしょうか。そして社外では勉強会などで積極的に発表し、解析ノウハウを共有し技術向上に努め、社外の多くの同業種の人と交流を深め、また自身のスキルを広く理解してもらうことではないでしょうか。
特に社外に向けての情報発信はとても重要だと思います。それは業界やコミュニティ発展に大きく寄与することになりますし、今後より良い環境で仕事をしていくための重要な足場作りになります。
2011年は解析者にとって良くも悪くもチャンスの年
2011年はそういった意味で良くも悪くも解析者という存在を認めてもらうためのチャンスの年であると感じています。良いことはHadoop等の大規模分散処理技術やNoSQLの普及によってそれまでお手挙げだった、大規模のデータでも解析することが可能になってきて、それと共にデータ解析の重要性が一般に認知されるようになったことです。そこでデータに基づく戦略を数々打ち出す事ができれば、よりいっそう僕たちの存在価値は高まってくるはずです。
一方で悪いことは今のようなIT好景気がそれ程長く続かない事です。特にソーシャルゲームプロバイダのベンチャーにおいては去年以上の収益をもたらす事は難しく、かつ携帯電話上でのゲームからスマートフォン上でのアプリやその他のサービスへの転換という、大きな舵取りを迫られるはずです。そしてその向かう先は意志決定者にとっては不安だらけです。そういった時に僕たち解析者が彼らの意志決定に自身を持たせ、次にヒットするサービスの大きな下支えになれるかどうかで存在価値は変わってくると思います。
最後に
データ解析というとBtoB向けのアクセスログ解析という印象が強いと思いますが、WebサービスのようなBtoCでもソーシャルデータ特有の解析によって自社サービスを改善していく事での解析者の役割が非常に重要になってきています。GREEには当初からあらゆるデータをきちんとって、それを活かして行こうという気概を持った人とそれを認める文化があったからこそ今のような大規模なサービスを展開できており(えらそうな事をいってごめんなさい)、DeNAも同じく最近では @hamadakoichi さんが解析専門部隊を立ち上げて精力的に活動しています。BtoBで解析をやって来られた方々、解析に興味のある学生の方々、機会があれば是非ともこちらの業界に飛び込んできてみてはどうでしょうか?きっととても楽しいはずです。
参考リンク:
会社の成長を支えるデータ解析/GREE
2100万会員モバゲータウンはデータマイニングの宝の山
楽天技術研究所におけるウェブマイニング
今年も解析者として、普段の仕事もコミュニティ活動も、そして解析者の存在価値を高めていけるような活動も積極的に行っていきたいと思います。そしてたくさんの人に出会あい、刺激をもらうことをとても楽しみにしています。改めて本年も宜しくお願いします。
「第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyo」を開催してきました!
こんにちは、@doryokujinです。本日は12月12日(日)行われました「第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyo」の報告をします。当日は忙しい時期にも関わらずたくさんの人に参加していただきました。会場準備で色々を手間取ってしまいましたが、会場提供者のニフティさんと参加者の皆様の暖かいご協力もあって無事に勉強会を終えることができました。どうもありがとうございました!また、当日はgihyo.jpさんの協力のもと、Ustream配信も行いました。このUstream動画と共に勉強会報告の方をgihyo.jpさんの方にも書かせていただく予定ですのでぜひともそちらの方も宜しくお願いします。今回の勉強会のツイートがまとめられたTogetter:第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyoもなかなかが臨場感があって面白いですね。
当日の発表内容はこちらになります:
- 「MongoDB_JP 今後の活動計画」:@doryokujin
- 「MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜」: @doryokujin
- 「Ameba PicoとMongoDB」:@snamura
- 「Big Couch & CouchDBからのお知らせ」:@yssk22
- 「PostgresSQLからMongoDBへの以降 -アシストオン通販サイトでの実際-」: @basuke
- 「センサーデータストアとしてのCouchDB 〜そうだ、Couchに入れよう。〜」:@motokazu
- 「MongoDBと位置情報 〜地理空間インデックスの紹介〜」:@madapaja
- 「CouchDB on Androidでスタンドアローンアプリ。」:@mkouhei
MongoDB_JP 今後の活動計画
僕の方からは前説としてMongoDB JPの今後の活動計画についてお話しさせて頂きました。ここでの本題は、直近の大きな目標として2011年3月に「MongoDB Conference in Japan」を開催したいという宣言です。(数百名規模を収容する)会場提供者・発表者・スポンサー・協力者を広く募っております。どうぞ宜しくお願いします。
MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
今回も相変わらずログ解析におけるMongoDBの活用事例をお話しさせて頂きました。3ヶ月以上MongoDBを解析データサーバーとして使ってきて改めて感じるのは、検索クエリの豊富さ、コンソールの扱いやすさ、node.jsやRESTといった機能によるデータの取り出しやすさに非常に助けられているということです。解析者に優しいデータベース、それがMongoDBです。また最近データ量が増えてHadoopとの連携がより重要になってきています。MongoDBの開発元である10genもHadoopとの連携を積極的に進めているようですので今後の動向に注目しつつ、それらの機能は積極的に検証していきたいと思います。
Ameba PicoとMongoDB
@snamuraさんからは、累計登録ユーザー数 3,000,000、MAU 560,00を誇る大人気サービスAmeba Pico(アメーバピグの海外版)のMongoDBでの運用について、その具体的な方法と注意点などについてお話していただきました。日本でのMongoDBでの運用事例は非常に稀少ですし、ましてやShardingやReplicationをいったスケーラビリティを考慮しないといけない大規模についての事例はとても貴重です。AmazonEC2での具体的なサーバー構成をお話ししていただいた後、遭遇した様々な問題点とその対象方法を具体的に述べていただきました。例えばShardingが偏ってしまう問題はfoursquareでも発生していて、それにどう対処するのかなどは非常に参考になりました。さらにサーバー負荷のモニタリング方法やJava Asynchronou Driverの開発など、ハイレベルなMongoDBの活用事例に見習うところはたくさんありました。本当にありがとうございました!
Big Couch & CouchDBからのお知らせ
@yssk22さんからは CouchDBとCouchDB JPの2010年の活動を振り返えったあと、Big Couchについてお話ししていただきました。CouchDB JPの皆様は非常に精力的な活動を続けられていますので、MongoDB JPの方も負けじと頑張っていきたいですね。
CouchDBとは何か、Big Couchとは何かの紹介を面白くわかりやすく紹介していただいたあと、Big Couchの仕組みと動かし方を詳細に発表していただきました。特に実際の動かし方の手順をわかりやすく述べて頂いたあと、様々な実験検証を行い、q: シャード数・n: 複製するシャード数・w: 書き込み保証数・r: 読み込み保証数のトレードオフと、それによる運用の難しさをお話ししていただきました。素晴らしい内容でした。ありがとうございました。また、@yssk22さんはnode.jsに関して色々と活動をされているみたいなので、そちらの方にも注目・期待しております。
PostgresSQLからMongoDBへの移行 -アシストオン通販サイトでの実際-
@basukeさんからは、構造がしっかりしていないといけないECサイトながら、様々なオーナーの要望に応えないといけないという状況の中でその双方の制約を叶えるのがMongoDB、というステキなイントダクションの後に、原宿の人気セレクトショップのECサイト:アシストオン通販サイトを事例にしたMongoDBを使った環境への移行についてお話ししていただきました。元々の構成(PostgresSQL + PHP)から新しい構成(MongoDB + Lithium)への移行について、LithiumでどうMongoDBからデータを取得するのか、その時にどういった所に注意する必要があるのか、その方法と注意点が非常に具体的で非常に参考になりました。さすが@basukeさん、非常に話し上手でわかりやすい、最後まで魅力的な発表でした。ありがとうございました。
センサーデータストアとしてのCouchDB 〜そうだ、Couchに入れよう。〜
@motokazuさんからは、CouchAppを使ってとにかくあらゆるデータをCouchDBに入れていこうという話。なんとそのデータの対象が家の中のセンサーデータという斬新な題材であったので、会場は大いに盛り上がりました。「Arduino + ethernet shield + センサー」をCouchDBでモニタリングすれば数千円でオール電化が実現しますとのこと(笑)。SDカードにCouchDBを入れて、ACアダプタサイズのサーバに挿入すれば簡単にホームサーバーのできあがり。構築なんて必要無い、Relax。CouchDBの良さを活かした面白いプレゼンでした。ありがとうございました。sensmonは商標登録した方がいいですね。
MongoDBと位置情報 〜地理空間インデックスの紹介〜
@madapajaさんからはMongoDBの特徴的な機能でありながら実はあまり知られていない(かもしれない)地理空間インデックスについて、丁寧にお話ししていただけました。2次元の地理空間情報インデックスして検索が行える機能がver.1.3.3以上で使えるようになりました。Indexの作成の仕方から$near、$maxDistanceなどのクエリ使った検索の仕方について、具体例とともに紹介していただきました。しかし「地球は丸かった」(笑)ということで平面上での近傍検索しか行えない先ほどのクエリに対して、$Sphere という球体情報を考慮した画期的なクエリ(ver.1.7)についてお話し頂きました。非常にエキサイティングで面白かったです。ありがとうございました。
CouchDB on Androidでスタンドアローンアプリ。
@mkouheiさんからは最後の締めを飾るにふさわしく、まさに漢の家計簿管理方法:「CouchDBとJQueryとCouchAppを用いた家計簿管理アプリ」についてデモともにわかりやすくご紹介いただきました。ポイントはJavaScriptのみで書かれたスタンドアローンアプリであることで、それだけで簡単に実務に役立つアプリが作れてしまうということです。CouchDBの面白いところですね。最後にCouchDBをjquery-mobileで使用する際の注意点などをお話ししていただきました。CouchDBとモバイル端末との連携はアツいですね、今後に期待です。ありがとうございました。
最後に
ユーザーグループの主催、勉強会の主催というのを今回初めて経験させてもらっていますが、非常に楽しく刺激的でもあり、一方で色々と大変だなぁというのが正直な印象です。しかしそこに非常にたくさんの方々の協力支援があって、着々と良い方向に向かって前進していることを確信しています。これからも皆様のお力を借りながら、これらの活動がもっとたくさんの人達を巻き込んで、ハッピーにしていけたらなぁと思っています。いつも助けていただいている皆さん、本当にありがとうございます。今後ともどうぞ宜しくお願いします。
MongoDBドキュメントチュートリアル
こんにちは@doroykujinです。まずは皆さんのおかげでMongoDB JPを立ち上げることができ、かつ150名以上の方に参加していただいている事に感謝したいと思っています。今後積極的な活動を行っていきますのでどうぞ宜しくお願いします。
さて、本エントリーはMongoDB JPの方で日本語ドキュメントを手伝ってくれる方を募集し、かつどの部分を翻訳したいですかと尋ねたところ、「ドキュメントの構成がどうなっているのかわからない」という貴重なご意見を頂きました。確かにおっしゃるとおりでどのようなドキュメントの構成なんてわかりませんよね、しかもそれをすぐに把握するのも大変ですし。そこで今回はドキュメントがどのような構成になっているのか、ドキュメントに沿ってMongoDBの機能を簡単に紹介するようなチュートリアルをやってみたいと思います。そういう意味で全て本家ドキュメントからの引用になります。
なお、前エントリー、MongoDBのちょっと詳しいチュートリアルも参考になると思いますので宜しくお願いします。
※日本語ドキュメント訳には現在10名程度の方が手を挙げて下さっています。本当にありがとうございます。実際の進め方や管理方法、用語の統一など、スムーズな作業ができるようにそちらの環境を整えていきますので宜しくお願いします。もし経験者の方で複数人での訳の進め方について何かアドバイスがございましたらコメントいただけると幸いです。
ドキュメントインデックス
現在のドキュメントの目次は以下のようになっています。本日のアジェンダはこの目次に沿って行きたいと思います。フライングしますが、Aboutのページはあまり読まれなかったりしますが、かなりの情報が詰まっていますので是非とも見落とさずに読んでみて下さいね。
1. Introduction
まず一番初めに見るべきイントロダクションです。10gen CTOであるEliot Horowitz氏の言葉に始まり、MongoDBの特徴、
- Document-oriented
- High performance
- High availability
- Rich query language
が簡単に書かれています。箇条書きで詳しく書かれていないのであまり読む必要は無いような気がします。
2. Quickstart
Windows、Mac、Linuxでのインストール手順が記載されています。各種32bit/64bitが選べますが、オンメモリーデータベースにおける32bitの利用はデータが2GBに限られるというかなり厳しい制約を受けるため、できる限り64bitをインストールするようにして下さい。
3. Downloads
本ブログ執筆時点(2010年11月22日)の最新安定バージョンは 1.6.4 です。このバージョンでかなり多くの改善がなされたので、今から導入される方はこのバージョンをお薦めします。1.6 Release Notesより、主な変更点を記しますと、
Sharding
Sharding がこのバージョンで初めて正式にサポートされました。スケーラブルで単一障害点を持たず、設定・管理が非常に簡単で、かつ現在の単体構成から容易にスケールさせることのできるMongoDBの魅力的な機能です。
Replica Sets
従来のMaster/Slave構成・Replica Pair構成に加えて新たにReplica Sets構成が加わりました。正しく言えばReplica Pairの拡張で、Pairの2台構成からSetsは7台構成まで可能になりました。ではなぜ7台なのか、その台数で必要十分であるということをMongoDBの代表的なプロダクションカンパニーであるBoxed IceのブログWhen would ever need more than 7 replica set members?で書かれています。Boxed IceのMongoDBに関するブログ記事はとても参考になります。
その他 - クエリの強化・64bit
その他、いくつかの機能が改善されています。例えば$or、$slice オペレーターが増え、1コレクション当たり64インデックス(以前は40)を作成できるようになりました。
4. Drivers
MongoDBは非常に多くの言語でドライバをサポートしています。ここに掲載されている以外でも多数のドライバが存在します。また、RubyOnRailsやDjango、@cakephperさんの作られたCakePHPといったフレームワークのORMとしてのライブラリも各種充実しています。現在サポートされている言語は、
になっています。さらに最近ではRからMongoDBを呼び出せるRmongoやmongo-hadoopといったHadoopとの連携をサポートするツールも公開されるようになってきました。特にHadoopとの連携は今後サポートを強化していくという正式アナウンスがありました。今後が楽しみですね。
5. Developer Zone
さて、MongoDBの機能を説明してあるページはこのDeveloper Zoneと次のAdmin Zoneになります。Developer Zoneでは、機能説明であるManualに入るまでにその他紹介されている事項を先に記入しておきます:
cookbook.mongodb.org
MongoDB Cook Bookです。といってもそこまで豊富なTipsが掲載されているわけではありませんが、あるコレクションからデータを一様ランダムに抽出する方法、MapReduceのサンプルなどが掲載されており、今後Tipsが増えていくことを期待しています。
Tutorial
こちらのチュートリアルは具体的に手を動かしながらMongoプロセスを立ち上げ、基本的な挿入・検索コマンドからどんな値がどのような形式で返ってくるのかを具体的に指示してくれています。こちらは有用なので一読をお勧めします。
mongo - The Interactive Shell
MongoDBはシェル上でCRUDの操作やReplicationやShardingの管理構築ができます。実はMongoDBのコマンドはJavaScriptで書かれており、わかりやすい形式でコマンドが表現できます。また、ユーザーが関数を定義することもできますし、定義関数が書かれたJSファイルをシェル起動時に読み込ませることもできますので非常に便利です。このシェルこそ最もMongoDBらしい部分かもしれません。
Developer FAQ
ネームスペースとは何か?どのRAIDで構成すべきか?などの興味深い点についての説明がなされています。最後の質問、「Why are my data files so large?」MongoDBは保存するデータサイズが巨大になりがちなのですが、これについての説明がされています。実際運用するに当たってはディスク・メモリ使用量やフラグメンテーションといった部分が気になると思います。前エントリーの「foursquareの11時間にも及ぶサービスダウンの原因を詳細に調査してみた」もこの辺りに少しだけ関係してきそうです。
Manual
Developper Zone、主に使用者(反対は管理者)が扱うための主要な機能が網羅されているManualになります:
Databases
シェル上でMongoDBを扱うためのガイドです。シェル上のコマンドは管理者向け、CRUDを行うため、サーバーステータスを確認するため、といった様々な用途で使用する事ができます。前述しましたようにJSで記述されています。API Documentationでソースを読むこともできます。
Collections
MySQLのテーブルのような概念はMongoDBではcollectionと呼びます。MongoDBのcollectionはまたBSONドキュメントの集合になっています。MongoDBから取得したデータはたいていJSONとして扱うのですが、内部的にはJSONよりも(多くの場合で)効率的なBSON形式でデータ格納されています。
- Capped Collections
Capped collectonsはあらかじめサイズの固定されたcollectionで、サイズがいっぱいになった場合は古いデータが消されて追記されて行きます。Capped collectionsは書き込みが非常に多く発生する場面(ロギングなど)において非常に高いパフォーマンスを発揮することが期待されます。現バージョンではオブジェクトの削除ができないなどのいくつかの制約がありますが、それが問題にならない特定の用途に対しては最適な選択になります。MongoDB自身のオペレーションログ(oplog)はこのCapped collectionで構成されています。ですのでoplogは初めに大きめのサイズを指定しておくことで障害時の復旧時などのロールバック時に役立ちます。このページは今後MongoDBをよりうまく活用したい場合などに有用なページになりますし、色々丁寧に書かれていますので一度読んでおくことをお薦めします。
Data Types and Conventions
MongoDBに格納されたオブジェクトのDocument IDである "_id" キーについて、BSONについて、MongoDBのデータタイプについてやや詳しく記述されています。また、MongoDBはUTF-8での正規表現をサポートしています。
GridFS
他のDBが持たない希有な機能の代表としてこのGridFSがあります。これはMongoDBで大容量のファイルを扱うための仕組みを提供してくれます。BSONでのオブジェクトサイズの上限は4MBですが、GridFSはそれ以上の例えばビデオや音楽ファイルを扱うことができます。大きなファイルを複数のファイルに分割して、それがあたかも一つのデータであるように扱っています。各種言語向けにDridFS APIが用意されています。
Indexes
MongoDBは完全なインデックスをサポートしており、あらゆるキーに対してそれを作成することができます。ここではインデックスの詳細な利用方法が記述されています。運用上重要な項目ですが、しっかりと書かれていると思います。最後にここで特筆すべき事として、Geospatial Indexing(地理情報インデックス)をサポートしていまして、例えばfoursquareは積極的にこのインデックスを活用しています。
Querying
MongoDBでのクエリーの作り方について書かれています。MongoDBが豊富なクエリを持つことは、Advanced Queryから確認できると思います。このページはとても読んでいて楽しいです。また、countやdistinctといった集約関数も使えます。
Optimization
最適化の説明になります。MongoDBの性能を落とさない/性能を導き出すための様々な提案が書かれています。インデックスを張る、必要な項目のみを指定して取り出す…などの重要な情報がたくさん書かれています。
Inserting
データの挿入方法についての説明です。MongoDBへの挿入データはJSON形式で記述します。挿入オブジェクトにはかならずDOCUMENT IDである一意なキー "_id" が無いといけません。キーに含まれていない場合は自動で作成されます。Schema DesignではMongoDBにおけるデータのスキーマデザインについて詳しく書かれています。また bulk insert という高速にinsertを行うための機構を備えています。
Removing
MongoDBのオブジェクトを削除します。removeコマンドは基本的には検索と同じように条件を指定し、それに合致したオブジェクトを削除します。条件を指定しない場合は始めの1件だけが削除されます。
Updating
MongoDBには基本的なupdateコマンドに併せて、Modifier Operationsという非常に高速・効率の良い更新方法を備えています。オブジェクトの特定のキーの値のみをインクリメントするする場合などで用いることができますが、他にも$inc、$set、$push、$addToSet、$pop、$pull、$renameなど、なかなか多くのModifierコマンドがありますので、updateの際はまずはModifier Operationを検討してみて下さい。
MapReduce
MongoDBはShardingを行っているサーバー間でMapReduceを実行することができます。また、大規模のコレクションに対するgroupなどの一部の集約関数はMapReduceで代用することが推奨されています。サンプルコードたくさんあってそれなりに丁寧な説明がなされています。
6. Admin Zone
続いてAdmin Zoneの紹介です。こちらはMongoDBの監視からReplication、Sharding、バックアップの方法などの機能が紹介されています。
Production Notes
基本のTCP port番号は、
- Standalone mongod : 27017
- mongos : 27017
- shard server (mongod --shardsvr) : 27018
- config server (mongod --configsvr) : 27019
- web stats page for mongod : add 1000 to port number (28017, by default)
Replication
Replicationの主要な2つの構成、Master/SlaveとReplica setsについて、詳細に記述されています。Replica sets は現在のPrimaryに障害があってダウンした場合、自動的にメンバー内で次のPrimaryを選択するフェイルオーバー機能を祖備えています。MongoDBのレプリケーションとバックアップ機能の紹介に少し詳しく書いています。この部分のドキュメントは多数のサンプルコードが使われており、実際に自分で手を動かしながら動作の確認を行う事ができます。
Sharding
MongoDBのShardingはこちらがキーの分割の仕方を示してやらなくても、自動で適切に配備した複数のサーバーに割り振ってくれます。また、Shardingしているサーバー間でMapReduceを行うこともできます。まずSharding IntroductionにてMongoDBにおけるShardingを丁寧に解説してもらった後、Configuring Shardingで実際に設定方法が細かく記載されています。前述のReplicationとこのShardingの部分はかなり丁寧なドキュメント構成になっている印象を受けます。
Hosting Center
非常にホットな話題です。MongoHQなどのホスティングサービスの紹介から、AmazonEC2上で動かす方法まで、簡単ですが述べられています。
Monitoring and Diagnostics
現在のMongoDBの状態の監視・診断といって、管理者にとっては重要な項目です。muminやgangliaで状況を確認するアダプターも存在しています。
Backups
データファイルをコピーしてバックアップする方法、Slaveの同期によって行う方法、mongodumpコマンドを利用してエクスポートする方法など、いくつかの方法が提案されています。2番目のReplicationのメンバーを追加することによってバックアップを行う方法は、データのが大きいと非常に多くの時間がかかる場合があるので注意が必要です。
Admin UIs
MySQLのphpmyadminのような、UIから直感的にMongoDBを扱えるツールが多数スクリーンショット付きで紹介されています。僕も一通り試してみましたが、結局はシェルで操作するのが一番柔軟で楽なので使わずに終わっています。ただ、管理者以外の複数のメンバーがデータを閲覧できる方法として考えると非常に便利かもしれません。
その他
その他細かい項目がありますが、割愛させて頂きます。
7. Contributors
Contributer向けのルールや加入方法などについて記載されています。肝心のドキュメント翻訳のContributing to the Documentationになっていますが、日本語ドキュメント訳を手伝って下さる方を募集しています。MongoDB JAの募集スレッドからの返信か、僕@doryokujinに連絡いただければ申請を行いますので是非という方は宜しくお願いします。
8. Community
はなかなか重要な情報が満載です。まず本家ユーザーグループ・IRC・Blog・バグトラッカーへのアクセス方法が紹介されています。そして現在の開発陣の紹介、そしてジョブボード。非常に個人的な意見ですが、Looking for Data Scientistsという役職があるのが海外らしく、かつ大変興味深いですね−。QualificationsにHadoopやPigやMapReduceと書かれていたりします。
9. About
完全に見落としがちなAboutページですが、MongoDBを全体を俯瞰して理解を深めるにはここが最適です。なぜならば、Slide Galleryにて今まで紹介してきたMongoDBの機能がスライドでわかりやすく紹介されており、またUse Casesではロギングやテキストサーチといった具体的なMongoDBの利用例が紹介されています。Production DeploymentsではMongoDBを活用する企業の名前が資料とともにリストアップされています。この資料がとてもわかりやすいので、色々読まれてみる事をお薦めします。 BenchmarksではMongoDBとMySQL、あるいはCouchDBなどといった他のDBとの比較を行った記事のリンクがあります。こちらも非常に参考になります。
11. Books
現在出版されているMongoDBに関する書籍の情報です。MongoDB The Definitive Guideはやや薄めの書籍ですが、ReplicationやShardingといったAdmin Zoneの内容について、その原理から具体的な構成方法まで記述してくれていますのでお薦めです。 The Definitive Guide to MongoDB: The NoSQL Database for Cloud and Desktop Computingの方は時が少し読みにくいのと、ドキュメントとかぶるところが多いのですが、こちらもしっかり書かれているので勉強になると思います。この2冊は買って持っていますが、どちらかと言えば前者がお薦めです。日本語訳本が待たれるところです。というより訳をしたいですよね。残りの2冊はまだ発売されていませんが、MongoDB in Actionは筆者のブログで色々と情報が公開されています。というよりとても貴重な情報源です。
最後に
いかがでしたでしょうか?以前のエントリー、MongoDBのちょっと詳しいチュートリアルはそれなりにまとめて書いていますので、こちらも併せて見て頂けると幸いです。今後はMongoDBの各機能にもっとフォーカスして具体例を出しながら紹介していきたいと思っています。今後とも宜しくお願いします。
MongoDB JP を立ち上げました!
こんにちは、@doryokujinです。本日はMongoDB JPの立ち上げに伴って、その告知と本グループにかける想いを少し書かせて頂きたいと思います。まずは改めて、
MongoDB日本ユーザー会:
MongoDB JP
を立ち上げました!興味のある方、ご登録宜しくお願いします!
記念すべき第1回勉強会&懇親会はCouchDB JPの皆様と合同で開催させて頂こうかと思っています。
2010年12月12日(日)
第1回 MongoDB & CouchDB 合同勉強会
※ 開催場所は規模などを見て後日ATNDとメーリングリストで告知します。
※ 現在MongoDBに関する発表者を募集中です。是非とも、という方がいらっしゃれば@doryokujin 宛かメーリングリストに連絡宜しくお願いします。
今回の立ち上げに当たってはCouchDB JPの@yssk22さんと@mkouheiさんの温かい支援も頂きました。今後とも情報交換として、また良きライバル(!?)として交流を深めていきたいと思っています。
さて、この告知で大方の目的は果たしましたが、時間のある方は以下のアジェンダでのお話に付き合っていただければ嬉しいです。
- 設立に至る経緯
- 目的
- 活動内容
- (個人的な)目標
設立に至る経緯
業務でMongoDBを活用してみて
僕自身、MongoDBに出会ったのはつい2ヶ月程前の事です。現在アルバイトをさせてもらっている芸者東京エンターテインメントでの業務、ソーシャルアプリのログ解析(資料1、資料2)において散在する各種ログを集計・集積し、かつ解析側が自由にアクセスできるような解析データストレージを検討していたところ、MongoDBに出会い、現在はソーシャルアプリ2種・1TB近くのデータ容量・10億レコード以上を保持し、解析基盤の中枢を担う役割として日々活躍してもらっています。
運用を進めるに当たって感じたことは2点ありまして、
- 非常に扱いやすく・高機能で様々なシーンでもっと活用できるはず
- 日本ではMongoDBに関する情報が圧倒的に少ない
そしてこのどちらもが今回の設立における原動力となっています。
- 非常に扱いやすく・高機能で様々なシーンでもっと活用できるはず
実際にログ解析という用途でのMongoDBの運用でも、非常に多くの機能を最大限活用させてもらっています。スキーマレスでありながら豊富なクエリをもち、完全なインデックスをサポートし、かつレプリケーションやシャーディングが非常に容易に行え、コンソールから何でも操作できて…そういった機能はログ解析に限らず様々な用途での活用にもベストな選択になりうると感じるようになりました。例えば、
のようなものがMongoDBを使うことでかなり楽にできる気がします。比較的新しいサービスが日本からもドンドンと生まれて来て欲しいなと考えています。
- 日本ではMongoDBに関する情報が圧倒的に少ない
海外ではfoursquareの利用を始めとして、MongoDBを活用したサービスが多数存在し、かつ本家ユーザーグループでの議論がとても盛んに進んでいます。ただ、現在のところまだ日本ではMongoDBという名前はあまり知られていない現状であり、それ故に日本語の情報がとても少ないです。こういった部分がネックになってさらに利用が遠ざかっていってしまうのはとても残念なことだと思います。
日本からもMongoDBに関する情報をどんどん増やしていって、企業から個人利用に至るまで、誰でももっと気軽にMongoDBに触れるようになったらないいなと思います。さらにこちらからどんどん技術のフィードバックを出していって、MongoDBの開発自身にも貢献していければと思っています。
後は思い切りですよね
日頃業務でも社員の方々には色々MongoDBの話を聞いてもらっていたり、個人的に仲良くしていただいている@ikumaさんや@darashiさん、 @kei_sさんとMongoな話をしていたりして、ユーザー会を立ち上げてもっとMongoDBの事を知ってほしいな、色んな人に会いたいなと思っていました。
そんな想いが募りに募ってきた頃、ちょうど先日、@cakephperさん、@kaz_29さん、@basukeさんという、PHP界の第一線を走られかつとてもMongoなアツイ方々とお酒を飲む場がありまして、「じゃあやろう!」という話でその場で盛り上がりました。そして@cakephperさんのこの強烈な後押しによって、思い切ってその日にTwitterで告知したという経緯になります。ありがたいことに非常に多くの方の反応があり・温かいお言葉をたくさん頂いて、今はなんでもっと早くやらなかったのかと思っています。まあ、本当に大切なのはこれからですからね、頑張ります^^。
目的と活動内容
何よりの目的はMongoDBの日本での普及です。普及という言葉にかける想いは、たくさんのエンジニアが門戸を叩いてくれるような「広がり」という側面と、熱心なエンジニアが議論を交わしあえたり勉強会で交流できるような「深み」を持った側面を持っています。
- [勉強会]:定期的な勉強会を通じて技術・情報交流を進めていきます。
- [交流]:CouchDB JPとの積極的な技術・情報交流を行ないます。
- [ドキュメント]:MongoDB日本語ドキュメントの整備を行ないます。
- [Q&A]:MongoDB活用に伴う問題・課題をメンバーで議論・解決していきます。
- [イベント]:MongoDBカンファレンスの日本開催に向けての働きかけを行います。
勉強会
勉強会は積極的に開催していきたいと考えています。また他のNoSQLとの比較や、MongoDBのサービスへの活用事例、Node.jsやWebOSとの連携の話など、他の技術やコミュニティとのコラボレーションなども積極的に行って行きたいと思います。
交流
本家ユーザーグループでは常に積極的な様々議論が行われていますが、こちらでもそういった議論やQ&A、情報交流が活発になり、それが多くの方の有用な情報源となっていく場を目指します。
ドキュメント
MongoDBドキュメントの日本語訳を整備していきたいと思っています。現在の日本語ドキュメント訳は最近僕も参加させて頂いていますが、今のほとんどの部分は@masatomonさん1人の貢献に寄るものです。より多くの方々に関わって頂き、ドキュメントの整備を勧めていきたいと思っています。他にも現在出版されているMongoDBに関する本の日本語訳などもできたらと思います。
イベント
これはあくまで個人的な想いですが大きなイベント、特に全国各地で開催されているMongo Conferencesを是非とも日本で開催させたいと思っています。
foursquareやbit.lyの中の人を呼んで是非ともお話を聞いてみたい!そのために10genの方々に積極的に働きかけて行きたいと思っています。それは個人的にも英語の勉強の良いモチベーションにもなりますし、頑張ります!あ、協力者も募集してます!
目標
最後に個人的な目標ですが、まずは海外で行われるMongo Conferencesに参加してきて、発表してきたいですねー。そこで色んな人と交流できればもっと色々な事ができそうな気がします!後は外国の方々にも注目されるようなサービスと技術を持った日本企業がProduction Deploymentsとして大々的に掲載されることです。
今まで色んな想いを述べさせて頂きましたが、どれも決して実現不可能なことで無いと確信しています。大事なのは”率先して手を上げること”、まずはその渦の中に飛び込んでいけば案外なんとかなるものですし、本当に困難な事があったときはきっと誰かが助けてくれると信じています。インターネット業界って、そんなステキな世界だと僕は思っています。今後とも率先してMongoDB JPの活動に取り組み、皆様に助けられながら大きくしていければと思っています。どうぞ、宜しくお願いします。
第8回データマイニング+WEB勉強会@東京で発表してきました。「MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析」
お久しぶりです。@doryokujinです。11/14(日)に行われました、第8回 データマイニング+WEB 勉強会@東京−大規模解析・ウェブ・クオンツ 祭り−で発表してきました。Togetterも参考にして下さい。
発表者・参加者双方の議論を重視するこの勉強会、今回もアツイ議論が絶えず巻起こって、とてもエキサイティングで有意義な勉強会でした。僕は前回に引き続き、今回も発表側として参加させていただきました。その時の資料は以下になります。
前回のログ解析バックエンドの続編として、散在する各種ログを集計してMongoDBに入っているデータを表・グラフとして可視化するためのフロントエンドのお話と、ソーシャルデータの解析をGraphDBであるNeo4jを用いて解析した事例を紹介させていただきました。解析方法の詳細はスライドの方に盛り込ませて頂いたので、今回は今までの解析の総括として以下のアジェンダでお話させていただきます:
- 解析用DBとしてのMongoDBの役割とそのメリット
- 3ヶ月の仕事を通して感じたこと
GraphDBに関しては次のエントリーでがっつりと書ける程のネタがありますので今回はスルーさせていただきます。
解析用DBとしてのMongoDBの役割とそのメリット
発表や懇親会で「なぜ解析用のDBにMongoDBを選んだのか?」という質問をいつも頂きます。今までのエントリーなどでもその理由をちょくちょく書いてきましたが、今回改めて書こうと思います。まず結論として、MongoDBを採用して間違いなかったことを確信しています。もしこれで無ければもっと基盤構築に時間がかかっていたでしょうし、もっとごちゃごちゃした構成になっていたと思います。といってもそれは作業者のスキル・サービス規模・社内環境/風土・リソース…といった様々な制約条件によって変わってくるものであると思います。なので僕はどのような制約条件の元で仕事をしているか、そこからお話をさせていただきます。
ここでは「データ」を様々なログの1つのレコード、あるいはそれを軽く集計した形でMongoDBに格納されたものと定義します。対して「指標」とはその(複数の)データから計算された最終出力としての数値と定義しておきます。
解析環境・ノウハウ、何も無いところからスタートした(ただ、ログはきちんと残しておいてくれていた)
もともと解析環境やノウハウが無いところからスタートしました。ソーシャルアプリの「おみせやさん」が大ヒットして、弊社が「お客さんにもっとこのゲームを楽しんでもらいたい」→「そのためにログ解析をきちんとやって科学的に仮説検証・実行していこう」というフェーズにあったところに僕が運良くジョインさせてもらったというのがそもそもの流れです。ちょうど8月のことです。ですのでこの課題のゴールとしては、
「とにかく色んなデータを採って検証してみたい」
という、なかなかふわっとしたものになります。例えば他のゴールとしては「PV、UU、ARPU…といった決められた基本指標を出して欲しい」といった場合もあると思います。数TBの手に負えない規模のログデータを持っていたり、そこまで解析を重視しない(そんな余裕がない)といった状況では、基本的な指標算出のみにとどまるでしょう。そういった取るべき指標が明確に決まっている場合はまた違った、もっと効率的な解析手法があったと思います。僕の場合はとにかく色んなデータを採取して見る必要がありましたので、まずログの情報がほとんど”生”の状態で保管しておく必要がありました。まずはどんなデータがあって、どんな数値・特性を持っているのか、そしてそれが今後の意思決定に必要なものになりうるか取捨選択、ということを解析者である僕自身が細かく確認していく作業をしていかないといけません。ですので、「解析者が必要な時に必要なデータを簡単に眺められて、その特性を見れる」
環境が必要でした。これは、- 常にデータが手元にある(社内から簡単にアクセスできる)
- 散在するログから抽出したデータは一つの場所に集約しておく
- データの特質を簡単に確認できるデータ保存方法である
ようにしなければならないという事です。今採れているおみせやさんのログは4種類、
で、これらを社内から解析者が簡単にアクセスできる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かというとその性質が
であったからです。
- ドキュメント志向であったこと
は人に読みやすい形式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などの大規模データ処理技術を使いこなせる能力や各種制約の下で適切なアーキテクチャを構築できる能力で、逆に前者はユーザー支点や多角的に物事を観察できる能力、各種ツールを使いこなせる能力です。ですので解析者がいない企業では、前者はインフラエンジニアが兼任し、後者はマーケティング担当や企画側が兼任することになると思います。もちろんどちらの知識も併せ持つことが重要ですが、もし解析者としてエキスパートになるのならば、どちらの方でそれを目指すのかということを考えていかないといけないかもしれません。解析者というと後者の方をイメージされる方、目指している方が多いかもしれません。僕は前者のバックエンドのほうでエキスパートを目指していきたいなと思っています。そこら辺の話はまた別の機会にしたいなと思っています。
とにかく今回の勉強会もとても有意義な素晴らしいものでした。運営者のみなさん、会場を貸していただいたニフティのみなさん、参加されたみなさん、本当にありがとうございました。今後とも宜しくお願いします。
MongoDBのレプリケーションとバックアップ機能の紹介
久々の更新です。MongoDBのドキュメントのReplicationの部分の訳が一応完了しましたので、それに合わせてこのブログでもReplication機能について書いていきたいと思います。まだ解釈の甘い部分も残っていますので、今後もこの部分の勉強を続け修正を行っていきます。また、引き続きAdmin Zoneの訳を進めていくつもりです。
本日のアジェンダです:
- MongoDBのReplication機能について
- Master/Slave
- Replica pair
- Replica set
- MongoDBのバックアップ機能について
- ファイルのバックアップ
- mongodumpによるエクスポート
MongoDBのReplication機能について
MongoDBのReplicationは細かく分けると3種類あります。
Master/Slave
典型的なMasterとSlaveの構成です。Masterが常に書き込み処理を行い、Masterに書き込まれたデータがSlaveに同期されていきます。ただ1つのMasterのみが書き込みに対してアクティブなことにより、強い一貫性(consistency)を実現します。ただ、それ以外のSlaveに対してもオプションで読み込み権限を与えることができます。これは結果整合性(eventual consistency)を採用しているためです。
MongoDBでMaster/Slaveの構成を実現するのはとても簡単です。Masterサーバーは自身がMasterであることを起動時のオプションで明示してやります。一方、Slaveサーバーには自身がSlaveであることと、Masterサーバーの居場所(source)を起動オプションで明示してやるだけです:
- master
//port: 27020でmasterサーバーを起動します。
mongod --master --port 27020 --dbpath /data/mongo/master
//--fork オプションとログの保存先:--logpath [log_path] を指定してやることでバックグラウンド起動もできます
mongod --master --port 27020 --fork --logpath /var/log/mongodb/mongodb.log --dbpath /data/mongo/master
- slave
今、Masterサーバーが同じlocalhost内で起動しており、Slaveサーバーをlocalhostの27021で、データの保存先を /data/mongo/slave として起動する場合を考えます。ここで必要なのは --slave オプションと --source [host (:port)] のみです。
mongod --slave --port 27021 --source localhost:27020 --dbpath /mongo/slave
また、1つのslaveで、2つの別々のmasterからデータを持ってくるといった事も可能です。こちらにその例があります。
Replica pair
Replica pairはMongoDBのバージョン1.6でReplica setに置き換わるまで、フェイルオーバー機能を備えたもう1つのレプリケーションでした。Master/Slaveとの大きな違いは、フェイルオーバーと呼ばれる、現在書き込みがアクティブなサーバー(primary)がダウンしたときに自動的にその他のサーバー群(secondaries)から1台をprimaryに昇格させて処理を継続させる機能を持っていることです。そしてReplica pairではその名の通り2台のサーバーで構成されるのに対し、Replica setは3台以上のサーバーで構成できるより柔軟な仕様になっています。現在Replica pairの採用は推奨されていませんが、こちらも非常に簡単に構成することができますので紹介しておきます。
- 起動
Replica pairとしてMongoDBを起動する場合、必要なのはペアとなるサーバー情報(host、port)と、arbiterと呼ばれるペアのどちらをprimaryにするかの決定を支援する独立したサーバーの情報です。今、同じlocalhost内でポート27020(pair1)と27021(pair2)と27022(arbiter)を使ってreplica pairを構成してみます。これはあくまで例であって、本来はすべてのサーバーは違うマシンで稼働させるべきです。得にarbiterサーバーは独立したマシンで起動させないと意味がありません。pair1を起動させる際に、--pairwith コマンドで相方のサーバー情報を、--arbiter コマンドでarbiterサーバー情報を明示します:
mongod --port 27020 --pairwith localhost:27021 --arbiter localhost:27022 --dbpath /data/mongo/pair1
同様にpair2も起動します:
mongod --port 27021 --pairwith localhost:27020 --arbiter localhost:27022 --dbpath /data/mongo/pair2
arbiterサーバーは特別なオプションをつけずに起動しておきます:
mongod --port 27022 --dbpath /data/mongo/arbiter
- arbiter
ここでarbiterについて少し説明を加えておきます。独立したマシンで起動されたarbiterサーバーは、replica pairのメンバーがネットワーク障害でお互いに通信できなくなった場合、どのデータベースをprimaryにするのかの決定を効果的に行う役目を持っています。もし --arbiter オプションを省略することもでき、この設定では通信ができなくなった場合、両方のサーバがprimaryとして動作することになります。しかし書き込みが双方のサーバーで継続して可能な場合、この状況ではデータの競合が起こってしまいます。
Replica set
Replica setはReplica pairに置き換わる機能としてバージョン1.6より追加されました。複数台以上のサーバーでのフェイルオーバーをサポートできるのが大きな特徴です。Replica setsにおいては以下の3種類のノードが存在します:
- standardノード
標準的なreplica setのノードです。データはこのノード間で完全に同期され、この内のただ1台だけがprimaryとなりその他はSecondaryとして動作します。どのノードもprimaryになる可能性を持っています。
- passiveノード
このノードは完全なデータの複製を保持しますが、決してprimaryになることはありません。
- arbiterノード
データの複製も保持せず、primaryノードにもなり得ません。このノードは現primaryノードに障害があったときに次のprimaryをsecondariesから選択する際の補助役としてのみ動作します。
Replica setとしてMongoDBを起動する場合には、--replSet オプションでsetメンバーに共通の名称を起動時に明示してやる必要があります。各サーバーを起動させた後、1つのサーバーでsetメンバーの登録設定を行います。その後、initiateコマンドによってすべてのsetにその設定が伝搬・反映され、Replica setとして機能するようになります。今回も簡単な例として、localhostのポート27020(set1)、27021(set2)、27022(set3)、27023(arbiter)を使用した構成例を示します。
mongod --rest --replSet myRepl --port 27020 --dbpath /data/mongo/set1
mongod --rest --replSet myRepl --port 27021 --dbpath /data/mongo/set2
mongod --rest --replSet myRepl --port 27022 --dbpath /data/mongo/set3
mongod --rest --replSet myRepl --port 27023 --dbpath /data/mongo/arbiter
続いてset1をシェルから呼び出してReplica setの設定を行います:
// シェルを起動
mongo localhost:27020
//config オブジェクトの作成
> config = {
_id: 'myRepl', //_idは--replSetで指定したset名
members: [ //メンバーの登録、_idはユニーク
{_id: 0, host: 'localhost:27020'},
{_id: 1, host: 'localhost:27021'},
{_id: 2, host: 'localhost:27022'},
{_id: 2, host: 'localhost:27023',arbiterOnly : true}] //arbiterノードに指定
}
//設定の反映
> rs.initiate(config);
{
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
//数秒後にReplica setはオンラインになって使用可能な状態になる
// > rs.status() で状態の確認ができる
- フェイルオーバー時の動作
それでは現primaryがダウンしてしまった場合、どのようにして時期primaryが選択されるのでしょうか?ここではオプションである優先度(priority)がすべてのsecondaryで等しいものとして話を進めていきます。現在のprimaryがダウンした際には最も直近で同期を完了したサーバーが優先的に次のprimaryとして選択されるようになっています。新しいprimaryとして選ばれたサーバーは他の健常なサーバーと同期を始めます。実は各サーバーにはデフォルトで1つの投票権(vote)を持っており、時期primaryの決定にはこのvoteによる投票が行われ、過半数のvoteを得たサーバーが晴れてprimaryとなります。各サーバーは現在通信可能なサーバーの中で最新のデータを保持しているサーバーへ投票します。過半数を得るためには少なくとも半数以上のサーバーが通信可能な状態でないといけません。そうでない場合は過半数票を得ることができませんのでprimaryが選ばれず、書き込み不可能な状態が継続します。これは2台のstandardノードで構成されるReplica setでも生じ、primaryがダウンした場合、voteは自身の持つ1つのみであるため過半数とみなされず、primaryを決定できません。よってこれにarbiterサーバーを加えた少なくとも3台以上のサーバーでReplica setを構成しないといけません。
※時期primaryの選ばれ方についてはまだ理解が浅く、もしかしたら上の記述は間違っているかもしれません(すいません)。その際はご指摘していただけると幸いです。
MongoDBのバックアップ機能について
ほとんどのデータベースにはデータのバックアップ機能を備えています。MongoDBにも大きく分けて2種類のバックアップ機能を備えています。
- ファイルのバックアップ
- mongodumpによるエキスポート
この2つの違いは主に前者は書き込み処理を止めて実行しないといけない(すなわちダウンタイムが生じる)のに対して、後者はサーバーを停止させずにバックアップを行うことができる点です。それでは詳しく見ていきましょう。
ファイルのバックアップ
ファイルのバックアップとは、直接MongoDBのデータファイルをコピーすることです。Linuxの場合、データパスは /data/db/ に設定されていますので、このディレクトリ以下のファイルをコピーすれば基本的にバックアップは完了します。また、このデータパスはデータベース(mongod プロセス)の起動の際にオプションとして指定することができます。例えば27020ポートを利用してmongodプロセスを起動し、かつ /data/mongo/master/ 以下にデータを保存したい場合は
mongod --port 27020 --dbpath /data/mongo/master
とします。このバックアップは非常に簡単ですが、いくつかの注意点があります:
- 書き込みが行われている途中でのバックアップは安全ではない
データベースが稼働中で書き込み処理が行われている際中にmongodのデータを直接バックアップするのは安全ではありません。データベースを一度停止させてバックアップをし、その後再起動する方法もありますが、mongoDBではコマンドライン上でfsyncコマンドを利用することでデータベースを停止させることなく、一時的な書き込みのロックを行って、その間にバックアップを行います。
- fsync コマンドを利用する
fsyncコマンドは元々まだ書き込みが行われていない処理を全て強制的に行うコマンドですが、安全にデータベースのデータファイルのスナップショットを取るためのロックオプションをサポートしています。ロックオプションが指定されたfsyncコマンドが実行されている間はすべての書き込み操作がブロックされます。この間にバックアップを行い、完了後にunlockコマンドでロックを解除して書き込み処理を再開するようにします。
> use admin //adminデータベースを使用します
switched to db admin
> db.runCommand({fsync:1,lock:1})
{
"info" : "now locked against writes",
"ok" : 1
}>// この間にデータのバックアップを行います…
>// バックアップ終了後は以下のロック解除コマンドを実行します。> db.$cmd.sys.unlock.findOne();
{ "ok" : 1, "info" : "unlock requested" }
> // アンロックが実行されましたが、これには少し時間がかかるかもしれません…
- バックアップしたデータからmongodを起動する際の注意
バックアップしたデータを例えば /data/mongo/slave/ に保存して、これをdbpathとして、
mongod --dbpath /data/mongo/slave
と実行使用としたときに、
old lock file: /data/db/mongod.lock. probably means unclean shutdown
recommend removing file and running --repair
see: http://dochub.mongodb.org/core/repair for more information
と表示されて起動に失敗することがあります。これは不意にmongodbがシャットダウンされた場合に、ロックされたままの状態になっているような際に起こります。このときは mongod.lock ファイルを削除して起動してみてください。
mongodump によるエクスポート
- mongodump
上述の方法では、一時的にMongoDBの書き込み処理を停止させてしますことになります。一方、このmongodumpによる方法はデータベースが稼働中でもデータベース全体をdumpすることができます。下記の例では、--outで指定したパスに--host で稼働しているMongodから--dbで指定したdbをバックアップしています。
mongodump --host localhost:27020 --db mydb --out /data/mongo/dump
- mongorestore
mongodumpでダンプされたファイルは、mongorestoreコマンドによってリストアすることができます。dumpされたディレクトリ以下には[collection名].bsonというファイル名でデータが格納されています。今、以下のmongodサーバーでリストアを行うことにします。先ほどdumpしたファイルが /data/mongo/dump にあるとします。このdumpファイルを /data/mongo/restore というディレクトリ以下にリストアするとします。まずはmongodプロセスを起動します:
mongod --port 27021 --dbpath /data/mongo/restore
そしてコンソール上で以下のコマンドでデータベース:mydbのリストアが実行されます。--dropコマンドは既に同じコレクション名が存在している場合には先にコレクションのデータをを削除してからリストアするオプションです。
mongorestore --port 27021 --db mydb --drop --dbpath /data/mongo/dump
終わりに
これまでに紹介した機能はMongoDBの持つ多彩なレプリケーション機能のほんの一部でしかありません。より細かな設定や他の機能は公式ドキュメント(日本語、英語)を参考にしてください。また、まだMongoDBのレプリケーション機能は万能ではありません。以前エントリーで紹介したFoursquareの事例のように、断片化の問題や、同期の遅さ、フェイルオーバーの失敗などが報告されています。しかしそのような問題も、提供元の10genとコミュニティの方々の活発な活動によってどんどん解消されていくだろうと思います。そして、僕もその活動に少しでも関わって行けたらと感じています。今後とも本ブログにおいてMongoDBに関するエントリーを続けていきますのでよろしくお願いします。他にもデータマイニング、勉強会報告、GraphDBなどバリエーションを増やしていきたいとも考えていますが、まずはブログ書く頻度を増やしていかないといけませんね…
foursquareの11時間にも及ぶサービスダウンの原因を詳細に調査してみた。<a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/doryokujin/20101014/1287000278" class="bookmark-count"><img src="http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/doryokujin/20101014/1287000278" tit
こんにちは、@doryokujinです。前回に引き続き、MongoDBに関するエントリーです。今回は10月4日にMongoDBが原因で起きた、foursquareのサービスダウンに関して、その原因や復旧に至る経緯を詳細に調査しました。TechCrunchJapanの記事、Foursquare:「対策を講じたはずなのですが、また6時間もダウンしてしまいました」にも紹介されていたのでご存知の方も多いと思います。MongoDBが原因で引き起こったとするならば、企業で実際に運用している僕にとっては放っておけない問題になります。実は5月にも長いサービスダウンがあったのですが、それはAmazonEC2の停電によるものでした。
本日のアジェンダです:
- foursquareにおけるMongoDB
- サービスダウン時の状況
- 本当にMongoDB自体の問題だったのだろうか
- サービスダウンの引き金となった出来事
- 本質的な原因はどこにあったのか
- 復旧後の状況
- foursquareの行なった対策について
foursquareにおけるMongoDB
foursquareのサービスにはScalaの言語が用いられ、WebフレームワークであるLiftを使用して作られています。現在130万人のユーザーを抱え、1日に 61.5万回のチェックインが行われています。これまでに5000万回のチェックインが行われました(2010年5月時点)。なお、8月末の時点で会員数は300万人を超えたとロサンゼルス・タイムズのインタビューの中で報じられています。
そして、チェックインの情報を保存しておくデータベースとして現在はMongoDBが使われています。元は1台のPostgreSQLインスタンスをデータストアとして使用していましたが、急速のサービス拡大に伴ってMongoDBに切り替えた経緯があります。切り替えた理由は主にスケールアップ(レプリケーションとシャーディング)の観点で、MongoDBの方がSQLデータベースよりもはるかに容易に導入・管理できるからと考えたためです。この機能が使えるMongoDBのバージョンは1.6からなので、foursquareはバージョン1.6(最新)を使用しています。チェックイン・Tips、そして現在地の施設などにつける、Venueと呼ばれるマーカ情報(とそれに関するデータ)がMongoDBに書き込まれていきます。
MongoDBはロケーション(+/- 180 degrees in each of 2 axes)に関するデータに対して特殊なインデックスを作成することができます。インデックスとして「"2d" index type」というタイプを使用することができ、例えば latlng: [40, -72]というロケーションを持ったvenuesというコレクション(SQLでいうテーブルに当たる用語です)に対して、
db.venues.ensureIndex({latlng: "2d"})
と、インデックスを作成することで以下のようなクエリーでの検索が可能になります。
- 与えられたロケーション[40,-72]に近いデータ20件を取得する:
db.venues.find({latlng: {$near: [40.72, -73.99]}).limit(20)
- 与えられたロケーションから各軸で1度だけ異なる範囲にあるデータを20件取得する:
db.venues.find({latlng: {$near: [40.72, -73.99, 1]}).limit(20)
さらに多くの情報は公式ドキュメント日本語訳の地理空間のインデックスを参照してください。
サービスダウン時の状況
- 10/04 11:00am EST - 片方のシャードにチェックインが集中していたために、パフォーマンスが著しく低下していることに気づく
- 10/04 12:30pm EST - この1時間半の間に偏りをなくすためのバランシングを試みたがうまく機能しなかった。そして新しいシャードを追加することでこの偏りを軽減させようとした
- 10/04 6:30pm EST - シャードの追加によっても1台のシャードのパフォーマンス低下が解決されなかったために、インデックスの再構築を行ない、メモリの断片化を修復することを決めた。この再構築にはかなりの時間と、データの損失や破壊の可能性があるためにバックアップ作業が必要になる
- 10/04 11:30pm EST - 5時間以上におよぶ再構築とバックアップ作業の後、サービスが復旧。幸いにもデータの損失などの障害は避けられた。
この約11時間の間、foursquareのすべてのサービスは完全にダウンしてしまっていました。
本当にMongoDB自体の問題だったのだろうか
foursquareのダウン時はまだデータベースの記録容量はまだ120GB程度でしかありませんでした。また直近のレポートでは1日約100万チェックインが行われ、これは1秒当たり60チェックイン(=書き込み数)が行われたことになります。この数値は大きいのかというとそれ程でもなく、例えばBasho on NoSQL performanceによれば、RiakとよばれるNoSQLで8ノード(16,000 TPS with 14 nodes)の構成で秒間10,000トランザクションをさばけたという報告があります。(Riakについてはこちらのスライドが参考になります。)なので、今回の問題はMongoDBの本質的な性能不足によるもの以上に、foursquareのMongoDBのデザインやトラブル対応に少し不備があったのではと考えるほうが自然になります。
サービスダウンの引き金となった出来事
foursqareではサービスダウン当時、AmazonEC2上で66GBのメモリを積んだ2台のマシンでシャーディング(データベースを分割することで負荷やディスク・メモリ容量を分散させる方法)を行なっていました。シャーディングはユーザーIDを元に行われていました。それまでの2ヶ月間の運用では、データは2台のサーバーに均等にうまく振り分けられていてどちらのシャードも約33GBのメモリを消費する程度で安定していました。しかし今回はこのバランスが崩れてしまったようで、サービスダウンの原因は
- 1. 片方のシャード(shard0とする)のメモリが物理限界の66GBをオーバーし、著しい性能低下を引き起こした
であったと報告されています。さらにその対策もうまくいかなかったわけで、
- 2. 第3のシャードを追加することによってshard0から5%のチャンク(データの塊)を移行しようとしたが、その後もshard0のメモリ容量が減らず、状況が解決されなかった
ために、復旧に11時間もかかってしまいました。しかし、幸いにも一部のデータが失われるといった状況にはなりませんでした。
本質的な原因はどこにあったのか
それではこれに関する本質的な原因をMongoDBの特徴と絡めて詳しく見ていくことにします。まず前者に関しては、
ユーザーIDをキーにした分割方法が適切でなかった
が考えられます。ちなみにもう片方のサーバーのメモリ消費量は50GBでした。ユーザーIDを分割のキーとしていたために、片方のシャードに何度もチェックインを繰り返すヘビーユーザーが偏ってしまう振り分けになってしまっていたとしたら、このような状況になってしまう可能性があります。また、後者の原因にはMongoDBが密接に絡んでおり、
インデックスに使用したメモリの断片化によってshard0の負荷を低減させることに手間取った
ことが考えられます。foursquareが記録していたチェックインに関するレコードは1レコード当たり約300バイトでしかありませんでした。実はMongoDBでは4KB以下のレコードの集合に関しては、それが別のシャードに移動したり削除されたとしてもインデックス作成に使用された一部のメモリは開放ずに残ってしまう(断片化)状況が起こってしまうのです。foursquareの場合は、データが連続しているチャンクから効率よくデータを移行することができずにこの状況が起こってしまいました。user-groupのDetails on FourSquare bug?において、新しいシャードの追加が素早く・効果的に機能するための条件として、Dwight Merriman (10gen)は以下のように述べています:
- シャードの条件に設定されたキーの振り分けが挿入順序で行われる場合
- ソースとなるシャード(ここではshard0)に高負荷がまだかかっていない状況時にシャードを追加した場合
- 1つ1つのレコードが4kBより少し上回る程度の容量を持っている場合
- もしこれらの条件のすべてを満たしていない場合は、速やかにデフラグを行い、断片化の進行を防ぐ必要がある
同サイトに、4kBより遥かに小さい大量のレコードで構成されたコレクションを作成して検証が行われています。このコレクションはインデックスに約300MBの容量を消費していましたが、このコレクションを削除したあとも2.3MBの容量を消費していることがわかります。さらにこのコレクションを作成しては削除するといった動作を繰り返すたびに、どんどん消費量が増えていっています。今回のケースでもこの断片化が引き起こされていたことが考えられます。さらに、他の2条件も満たしていなかったので、なかなか追加シャードへのデータの移行が進みませんでした。
復旧後の状況
その後shard0の復旧が進み、また3番目のシャードに一部のデータの移行が完了したために、現在はデータが均等に振り分けられ安定に動作していると報告されています。MongoDBには全てのインデックスを再構築するためのrepairDatabase()コマンドがあり、これを実行したようです。このコマンドは、すべてのデータが壊れていなかチェックし、壊れているものがあった場合取り除きます。またデータファイルを少し縮小します。しかし、容量の小さなチェックインレコードを大量に持ったコレクションによって引き起こされた断片化の問題に関しては本質的な解決には至らず、スレーブサーバーに repairDatabase() というコマンド(すべてのインデックスの再生成)を実行して最適化した後、このスレーブをマスターに昇格させることで約20GBの消費に抑えたと報告されています。また、今回明確となったMongoDBのボトルネックは、現在10genの技術チームが解決に向けて取り組んでいるとのことです。
参考(MongoDBのrepairコマンドについて):耐障害性と修復(公式ドキュメント邦訳)
参考(MongoDBのインデックスについて):インデックス(公式ドキュメント邦訳)
foursquareの行なった対策について
今回11時間にも及ぶサービスダウンはユーザーに対しての信頼を損ねてしまう結果になってしまいましたが、やはり新しい技術を使用する以上はこのようなリスクは避けられないと思います。しかし、foursqareはこのダウンの間、
- サーバーダウン中やバックアップ中である旨のメッセージをTwitterアカウント、 @4sqsupport と @foursquare が伝えた
- また、 @4sqsupport は毎時間ごとに定期的に状況報告を続けた
ときちんと状況報告に努め、かつこの事例から学んだことを、
- サービスの稼働状況を表示するサイト、 status.foursquare.comを新たに作成した
- より意味のあるエラーページを作成することにした。現在どのような状況でそれが起きているのかを詳細に記述するようにした
としてすぐにサービスに反映しました。僕はこの一連のきちんとした対応には好感を持っています。また、この大きな出来事を元にMongoDBがより良いものに、そして他の企業この事例を学んで同じ状況が起こるのを回避できるようになっていくことを願っています。
終わりに
今回、様々な海外サイトを参考にさせていただきましたが、英語面・技術面ともにまだまだ未熟ですので訳や解釈の違いが多々あると思います、その場合はご指摘していただけると幸いです。今回はMongoDBの少しネガティブな部分を書きましたが、他にも色々とネガティブな部分があることがわかっています。MongoDBのメリット/デメリットという軸でそのうちエントリーが書けたらなと思っています。
その他参考にしたサイト
- mashable.comより:
Foursquare Down for Nine Hours and Counting (UPDATED)
Foursquare’s 11-Hour Downtime: What Went Wrong
MongoDB CTO on Foursquare’s Scaling Issues
- myNoSQLより:
MongoDB Auto-sharding and Foursquare Downtime
Foursquare MongoDB Outage Post Mortem
追記(10/21更新)
後日InfoQより詳細な報告があげられていましたので追記してお伝えします:
InfoQ Foursquare's MongoDB Outage
また、この日本語訳も公開されていますので参考にしてください。
MongoDBのちょっと詳しいチュートリアル<a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/doryokujin/20101010/1286668402" class="bookmark-count"><img src="http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/doryokujin/20101010/1286668402" title="はてなブックマーク - Mo
@doryokujinです。本エントリーから数回にわけてMongoDBの紹介をつらつら書いていきたいと思います。日々、MongoDBの魅力にどっぷりな僕でして、それを少しでも多くの方に共有できたらというモチベーションで書いています。今回はチュートリアルとして主要な機能を少し詳しめに紹介していきます。アジェンダは以下の通りです:
はじめに
僕は現在MongoDBをソーシャルアプリのログ解析の中間集計データの格納・集約場所としてMongoDBを活用させてもらっています。MongoDB採用に至る経緯や使用目的については前々回のエントリーとスライドをご覧頂ければと思います。現在過去3ヶ月の行動ログや課金データなどの集計データのMongoDBへの格納がほぼ完了したところでして、現在約2億件のレコードが、シャーディングされた3台のマシンで管理しています。今後は実際のデータ解析を行いながら経営や企画の方々にデータの側から様々な提言をしていきたいと思っています。と、同時に誰でも簡単にデータを閲覧できるようなフロント部分の実装(Webアプリ)も進めて行く予定です。MongoDBにはmongooseというJavaScriptからMongoDBにアクセスできる非常に便利なライブラリーがありますので、これとテーブルや描画関連のAjaxを利用しながら効率よく作業を進めていく予定です。相関を求めたりモデル式を作成したりといった少し突っ込んだ解析にはRに全部任せてしまおうと考えています。このように、芸者東京エンターテインメント GTEにおいて、MongoDBはソーシャルアプリのログ解析のバックエンドとフロントエンドをつなぐ非常に重要な役割を担う存在となっています。
業務でのアプリケーションや実際のパフォーマンスにつきましては次回のデータマイニング+WEB 勉強会@東京 #TokyoWebMiningで発表させて頂きたいと思います。(次回は11月14日予定です。是非ともご参加下さい!アジェンダはこちらです。)
ちょっと詳しいチュートリアル
それではMongoDBとは一体どのようなDBなのか、今回は主に公式ドキュメントを参照しながら少し突っ込んだ形のチュートリアルとてして見ていきたいと思います。参考にした資料、詳しく書かれた資料などは随時リンクを張っていきます。
オープンソース
現在MongoDBは開発・サポート元である10genからオープンソースとして公開されています。彼らによって商用サポートも行われているみたいです。また、素晴らしいことに公式ドキュメントが非常に充実しています。公式ドキュメントの日本語訳もかなり進んでいます。この日本語ドキュメントは全て@masatomonさん1人の手によって運営されています。(ブログはこちら)@masatomonさんの日本語訳によってたくさんの方がMongoDBを知り、活用する機会が生まれたと思います。本当にありがとうございます。
NoSQL・ドキュメント指向データベース(JSON-like data schemas)
MongoDBは話題のNoSQL(Not Only SQL)の代表として今や多くの記事に取り上げられるようになりました。内部はC++で記述され、SQLと違ってスキーマレスであり、データはBSONと呼ばれるJSONに似た形式で格納されています。ユーザー側では完全なJSON形式として扱えます。弊社のソーシャルアプリ、おみせやさんのログ解析において格納しているユーザー課金データを例にしますと、
{
"_id" : "2010-06-28+000000+Charge",
"lastUpdate" : "2010-09-20",
"userId" : "000000",
"date" : "2010-06-28",
"actionType" : "Charge",
"totalCharge" : 1210,
"boughtItem" : { "おもちゃの素EX 5個" : 1,
"おもちゃの素 5個" : 1,
"ヌイグルミの素 5個" : 1,
"おすすめ看板" : 1,
"梅の湯" : 2 }
}
のような形になっています。
ドキュメント指向データベースは他にもCouchDB等が有名です。CouchDBとの機能比較については
に表があってとてもわかりやすいと思います。他にも、
が参考になります。
NoSQLにつきましてはたくさんの情報が公開されていますので各自お調べ頂けると幸いです。ここではとても詳しく各種NoSQLについて述べられたHPを紹介しておきます。比較表などもあってとても素晴らしい資料だと思います。これが無料で公開されていることは驚きです。
ドライバとして多くの言語サポート
◆各種言語向けドライバ
現在MySQLと同じくらい豊富にドライバが用意されています。公式にサポートされている言語は、
ですが、コミュニティサポートとして
C# and .NET, Clojure, ColdFusion, Erlang, Go, Groovy, Haskell, Javascript, Lua, Objective C, Scala, etc...
など、非常に充実しています。
さらにWebアプリケーションフレームワークのModelとしてMongoDBを扱うためのライブラリも用意されています。例えばRuby On Railsはここに詳しく書かれていたり、企業のRails+MongoDB活用事例としては、
- Why I think Mongo is to Databases what Rails was to Frameworks
- Scalable Event Analytics with MongoDB & Ruby on Rails
が参考になると思います。
◆Python+Django
僕はPythonを利用してMongoDBの操作を行っています。ドライバは2種類、
を確認しています。僕は前者のPymongoを使用しています。後者はまだ試した事がありませんので比較はしていませんが併せてDjango-MongoKitも用意されているので、Djangoまでの使用を考えるとこちらを使う方が一貫性があって良さそうです。その他のDjangoのサポートとして
- MongoEngine [O/RMapper]
- Django-Mumblr
- Django-MongoDB
があるみたいです。僕もDjangoの使用を検討していましたが、まずはmongooseをつかってWebアプリを実装しようと考えています。Python+Djangoに関してはこちらの記事が色々を参考になると思います:
その他のPythonでのMongoDB支援ライブラリとして、
などがあります。
完全なインデックスサポート
スキーマレスでありながら、完全にインデックスをサポートしているのがMongoDBの大きな強みであると思っています。MongoDBのインデックスは、MySQLのようなRDBMSのインデックスと概念的に似てて、MySQLでインデックスを付けたいような場所に、MongoDBでもインデックスを付ける事ができます。
先ほど例で示したおみせやさんの課金データに対しては、キーである、"_id" ・ "lastUpdate"・"userId"・"date"・"actionType"・"totalCharge"・"boughtItem"
の全てに対してインデックスを付けることが可能です。例えば"userId"に対してインデックスを作成する場合、以下のようなコマンドを指定します。
db.things.ensureIndex({"userId": 1})
スキーマレスですので、例えば"userId"が存在しないレコードがあるかもしれませんが、その場合は値がnullであるものとしてインデックスが付けらることになります。数字の1(-1)は昇順か降順を指定します。
さらにキー"boughtItem"の(連想)配列の要素に対してもインデックスを貼ることができ、
db.things.ensureIndex({"boughtItem.梅の湯": 1})
とすれば良く、"boughtItem"に"梅の湯"を含むレコードを高速に検索・ソートすることが可能になります。
他にも複合インデックスなど、非常に柔軟にインデックスを利用することができます。日本語ドキュメントに詳しく書かれていますのでぜひ一読してみてください。また、インデックスの情報は全てメモリ上に保存されることになりますので、大量レコードのDBに対して複数のインデックスを用いる場合は、十分なメモリ容量が必要になりますので注意して下さい。
リッチなクエリー
◆柔軟な検索条件指定
MongoDBにはダイナミックなクエリーのサポートがあります。様々な条件で柔軟な検索が行えます。HBaseやCassandraといった他のNoSQLでは不可能な検索条件もMongoDBでは可能です。こちらに様々な条件での検索方法が記載されています。例えば、
- 範囲指定
- 存在指定
- 配列のサイズ指定
- 正規表現
といった条件で検索可能になります。
◆集約関数
また、MySQLの "COUNT" や "DISTINCT"、"GROUP BY" といった集約関数も利用することができます。さらに大量レコードに対する集約関数の適用の際には"Map/Reduce"を使って、シャーディングされた複数のマシンのパワーを利用して処理を行う事ができます。詳しくはクエリーに関しては日本語ドキュメントのクエリー項目の、高度なクエリーと"集約関数"を参照して下さい。
そして、以下のMySQLとMongoDBのクエリー比較表が面白いと思います。
MySQLに類似した機能群
今までの機能を見て頂けた通り、MongoDBはNoSQLでありながら非常にSQLに近い機能を持っていることが伺えます。こちらのチャートにSQLとMongoDBのコマンド比較が載っています。
さらに現在ではMySQLのデータをそのままMongoDBへ移行した事例が多くの企業から報告されています。
レプリケーション機能
MongoDBにはMySQLと同じくレプリケーション機能を備えており、かつ非常に簡単な設定でそれを実現することができます。現在レプリケーションに関する機能として3種類用意されております。各々を簡単に説明していきます。ここではいきなりmongodコマンドを紹介していますが、これだけで簡単にレプリケーションが行えるという事を理解してもらいと思ったからです。
◆Master/Slave
あるMasterに対して、そのSlaveを構成する設定です。MasterとSlaveは基本的には入れ替わることはありません。まず、Masterにしたいサーバーに対して、MongoDBのプロセス起動時に
$ bin/mongod --master [--dbpath /data/masterdb/]
として起動します。--dbpathは明示的にデータの格納場所を指定するオプションです。Slave側ではこのMasterの場所を指定すればよく、
$ bin/mongod --slave --source
[: ] [--dbpath /data/slavedb/]
としてやれば自動的にMasterと同期を行ってくれます。その他のオプションとして同期間隔やMaster/Slave間のやりとりを記録するoplogのサイズを指定することができます。このoplogをより扱いやすくするライブラリも存在します。
さらに2つのMasterに対して1つのSlaveを構成するといったことも可能です。
◆Replica Pairs
Replica Pairsは状況に応じて、MasterとSlaveが自動的に入れ替える事ができるものです。例えばMaster側に障害があった場合には自動的にSlaveをMasterに切り替えて運用を続けることができます。さらにSlaveがMasterに切り替わった場合、新しいSlaveとして使用するサーバーもあらかじめ設定しておくことができます。こちらも設定は非常に簡単で、それぞれのサーバーで
$ ./mongod --pairwith
--arbiter
としてプロセスを起動するだけです。remoteserver は、pariの相手のサーバのホスト名です。 標準的でないポートで動かしたい場合には、 :port を付けてください。arbiterserverはある時点で、どのMongoデータベースがMasterとなるかを決定するのを手伝うMongoのデータベースサーバで、独立なサーバーとして起動します。
◆Replica Sets
Replica setsは"Replica Pairs version 2" として最新のバージョン1.6から導入された先進的な機能です。3台以上のサーバーのレプリケーションを行い、障害時には自動でMasterを切り替えることができます。こちらも設定方法はそれほど難しくありませんので、
公式ドキュメントやSetting up replica sets with MongoDB 1.6、またはpdf資料や下のスライドを参考してみてください。
オートシャーディング
MongoDBはCassandraやHBaseと同様に容易にスケールアウトさせる事が可能で、また複数台のマシンにDBを分割して配置することができます。これによって1台のマシンの負荷を低減させたり、ディスク容量も低減させることができます。MongoDBはこのDB分割自身を自動で行ってくれる機能を備えています。例えばユーザーIDが1000番台のレコードはこのサーバーに、2000番台は…みたいなことをこちらが考える必要がありません。(もちろんマニュアルに指定することもできます。)Auto Partithiningといわれるこの機能はYahooの[http://research.yahoo.com/project/212:title=PNUTS:やGoogleのBigTableと同じ思想で設計されています。
また、どれかのマシンがダウンしてしまった時も、そのマシンが担っていたデータは自動的に他のマシンに振り分けてくれます。Dynamoと同じConsistent Hashingを採用しています。ConsistentHashingについてはこちらがわかりやすいです。
またクエリーの所で紹介しましたが、シャーディングした複数のマシンパワーを利用してMapReduceを行うこともできます。
参考資料は本家ドキュメントと、以下の資料がわかりやすいと思います。
巨大ファイルを扱うGridFS
MongoDBは、バイナリデータの格納をBSONでサポートしています。しかし、MondoDBでのBSONオブジェクトは4MBのサイズに制限されているために、通常ではそれ以上のデータを格納することは不可能です。GridFSの仕様は、それ以上の大きいファイルを複数のドキュメントに透過的に分割する方法を提供します。これは、巨大なファイルを効率的に格納したり、ビデオなどの巨大なファイルを様々な方法で(例えばファイルの最初のNバイトを取得とか)効率的に扱うことができます。
今後の予定
さて、MongoDBに関しては今後とも積極的に情報を書いて行けたらと思っています。
より深い機能説明
今回はチュートリアルとして駆け足で紹介しました。今後はもっと内容を掘り下げて行きたいと思います。例えばシャーディングやレプリケーションに機能ついての詳細説明や、メモリーの消費量や32bitOSでの制約などを紹介していければと思っています。まずはMongoDBの特徴について今回よりもより詳しく書かれたNotes on MongoDBという記事を翻訳してみたいと思っています。
本家ドキュメントの翻訳
現在の日本語ドキュメントを作成していただいている@masatomonさんに協力する形で、今後僕も公式ドキュメントのAdmin Zoneの部分の残りの訳を担当させて頂くことになりました。現在のような質の高いドキュメントを維持できるかは不安ですが、皆さんのお役に立てる事を信じて、しっかりと訳を進めていきたいと思います。進捗はブログやTwitter等で告知していきたいと思っています。
勉強会での発表
今後とも勉強会には積極的に参加して、発表を通じて多くの方と議論をしていければと思っています。こちらは主に、現在仕事で行っている、「ソーシャルアプリのログ解析での(アプリケーションとしての)MongoDB」という位置づけで、前回に引き続き、リアルな話をしていきたいと思っています。
Production Deploymentsとして弊社の名前を掲載する
これは実は自分の中で大きな目標にしているのですが、MongoDBの公式サイトのProduction Deploymentsにソーシャルアプリでの導入事例として日本企業初として芸者東京エンターテインメントの名前を是非とも連ねたいですね…はい。
また、このサイトは他の企業がどのような用途でMongoDBを導入しているかという、非常に参考になる部分が多いページですので、ぜひともこのサイトの翻訳と各社の事例紹介を行っていきたいと思っています。
「解析者の立ち位置」について僕が思うこと。
こんにちは、 @doryokujin です。週に2、3回は更新しようと思いつつ、今週はこの1エントリーのみです…頑張ります。
本日のエントリーは僕の考える「解析者の立ち位置」について書いています。僕は自分の立ち位置(=役割)を明確にすることが、仕事で成果を出すための重要な要素かなと思っています。ところで、僕のこれから話す「解析者」というのは一般に認知されているような、いわゆる大企業の研究機関、「**研究所」と名のつく機関で解析に関する新しく高度な「手法」を生み出し、大規模解析基盤を構築し、論文もばりばり書き、手法や基盤それ自身が価値を持ち売上げになるようなエクセレントな人々の事を指すわけではありません。100人にも満たないwebベンチャーで、より現場に近い所でログ解析に携わる仕事をする人を指します。
本日の内容
- 新しいタイプの解析者が求められる時代に
- 解析者の仕事って何だろう
- 解析者の立ち位置とは
新しいタイプの解析者が求められる時代に
色々な場所で解析が必要になってきた
最近のWeb業界の勢いは本当にスゴイですよね。僕のバイト先の芸者東京エンターテインメント GTEが現在身を置いている業界、ソーシャルアプリ業界で特に顕著な話ですが、ベンチャー企業の10〜30人程の規模でありながら数百万人、時には数千万人のユーザー会員を抱えることができ、年間売上も10億円を超える企業も多数あったりします。そういった所では日々集積されるデータ(ログ)は1日に圧縮ファイルでも10GB以上、月に数百GB、時にはTB近くになったりします。また、完全なBtoCのサービスであり、従来のWebアクセス解析のようにクリックや遷移をウォッチするのではなく、ユーザーの行動や興味・関心といった所をウォッチして次の戦略に反映していかないといけません。そうした状況もあり、この業界でもデータに基づく様々な指標の重要性が再認識され、連日行われるソーシャルアプリのイベント等ではプロバイダーが「課金率はy%以上」とか「ARPUはxxxx円」とか、様々な指標とその目標数値を述べながら議論されるようになりました。そういった状況もあり、「解析者」や「データマイニングエンジニア」がこの業界でも求められるようになり、またその仕事の価値も少なくとも以前よりは上がったような気がします。
なぜweb業界の解析者は新しいタイプなのか
ではそういった解析者は前述したような研究所で働く解析者と同じような価値観で見られ、同じような結果が求められるのでしょうか?僕は全く異なっていると思っていて、全く新しいタイプの仕事だと思うんです。一番違うことは、求められるものが、手法の開発や高度な基盤構築自身ではなくて、それらをツールとして駆使し、何とかして自社のサービス向上のために施策を打ち出していくことにあると思っています。そのために「作る」側にも「使う」側にも回り、しかもエンジニアだけではなく経営者や企画者とも深く関わって行くコミュニケーションやフットワークの軽さが重要になってきます。ただあくまで理系専門家として、理論的に意見を出していく所ではマーケッターよりはもう少し専門的な仕事だと思っています。
解析者の仕事って何だろうか
それではより具体的にどのような仕事をするのか、ソーシャルアプリ業界で働く僕の日々の経験から考えてみたいと思います。
1. データを以前より多様な指標で集計
2. CMやイベントの効果の効果測定
3. UIやパラメータの複数のパターンから最適な設定を決定する
4. パーソナライズ:ユーザー個々に最適な設定を施す
5. 機械学習や強化学習を用いたサービス最適化
1. データを以前より多様な指標で集計する
もっとも基本的な仕事は、デイリーの集計を行うことです。先日の売上げやアクティブユーザー数・全体課金額などの基本的で大枠の部分は自動で出してくれるツールがあったり、プラットフォーム側で提供してもらえたりします。それではアイテムごとの課金額内訳はどうだったのか、のべでどれくらい友人と交流があったのか、などのより具体的な内訳を見れるようにし、かつ時間軸やユーザー属性の軸、課金の軸などの様々な切り口で眺められるようにします。これをレポートやWebから閲覧できる形にして関係者に提供します。
2. CMやイベントの効果の効果測定
ソーシャルアプリではミニイベントや機能追加、アイテム追加といった機能変更・追加がかなりの頻度で行われています。時にはCMを展開したりもします。なにせ競争がとても激しい業界ですので、逆に何もしないとすぐにユーザーを失ってしまいます。打ち出したイベントやCMの効果の大きさによって月の売上げは大きく変動します。なのでそういった各種イベントの効果を測定するのはとても重要な仕事になります。様々な指標の中のどの部分に効果が見られるのか、あるいは相乗効果はあったのかといった相関を見つけ出すといった所を調べていきます。
3. UIやパラメータの複数のパターンから最適な設定を決定する
前に述べた2つはいわば「過去」に対しての解析であるのに対し、ここでは「未来」に対して意志決定の支援を行います。例えば複数用意されたUIやパラメーターから最適なものを決定するといったことが挙げられます。ユーザーごとや時間毎に数パターンのUIやパラメーターを適用し、どの設定が最適であったかを統計的に決定します。しかし、誰の、何に対して最適を定義するのか、本当に最適なのか、といった判定は難しく、また全ての条件を同じにして比較することもできませんので、導き出された決定に何も考えずに従うのは危険かもしれません。
4. パーソナライズ:ユーザー個々に最適な設定を施す
解析ノウハウも蓄積され、データも蓄積されてパターンがわかってくると、ユーザーをゲーム継続期間や課金額といった属性でカテゴリ分けしたしていたところをより細かく、ユーザー個々に対して最適なアクション(パラメータ設定)を半自動で決定するといったことができるようになってきます。簡単なところでは1週間ログインしていないユーザーにはログインを促す通知を行う、といったものから細かいパラメーター調整、ユーザー個々のステータスに応じて例えば当たりの確率やレアアイテムの出現率を変更させて、テンションを維持させるための施策といったものが挙げられます。
5. 機械学習や強化学習を用いたサービス最適化
さらにもっと高度な技術である機械学習や人工知能といった技術を用いてサービス自身が学習し意志決定するようになれば、サービスの最適化を自動で行ってくれるようになれば、企画者や経営者の負担をだいぶ軽減させられる事ができます。例えばソーシャルリコメンドや自動イベント発生機能といった、パーソナライズよりもより目に見える形の施策を自動で打ち出していきます。
どこまでやるのか?
今述べたことが下に行けば行くほどより高度になっていき、現実味を失っていくのがわかると思います。そして、初めは企画者や経営者の意志決定を支援するような役割であったものが、彼らに代わって自動で意志決定を行うといった役割を持ったものに変わっていきます。そして僕たち解析屋としては、「機械学習やってます!」と言った技術アピールをしたいところです。しかしながら現実問題として、本当に5.のような所までやるべきなのかというと、僕は必要ないと(今のところ)感じています。できれば4.までやりたいところですが、実際は3.までできれば十分なのでしょうか?その理由としましては、
(a) 深い解析をやる時間も資金もない
(b) 企画者の打ち出すイベントに売上げが大きく依存している
(c) それがサービスや売上げの解析に(高確率で)結びつかない
(d) 解析結果を専門家以外理解できない
(e) 解析者個人の趣向がどんどん入り込んでしまう
などがあると思います。
(a) 深い解析をやる時間も資金もない
僕たちの打ち出すサービスは1年も持たないかもしれません、かつ次々に新サービスを同時並行にどんどん打ち出していきます。次のサービスにもきっちり対応していく事の方が重要ですし、短命のサービス1つ1つに時間もお金もそんなにかけられません。現実的に考えて、そこまで深い解析をじっくりやるのは難しいと思っています。
(b) 企画者の打ち出すイベントに売上げが大きく依存している
(c) それがサービスや売上げの解析に(高確率で)結びつかない
では、そもそもそんなに深い解析が必要なのかという問題ですが、たぶん必要ないと思います。それは売上げに関してもっとも重要な事は、企画者の打ち出すイベントの質や数、つまり人間の勘に大きく依存するからです。デイリーの課金額の推移を可視化してみると顕著になるのですが、平坦な部分なんて無いんです。あるのは山か谷のみ。そして山となるのはイベントを打ち出した時で、その後すぐに減少の一途をたどります。そして何もイベントをしないとどんどん課金額は落ちていきます。やはり機械的にはユーザーの心に刺さる施策を自動で見いだすのは困難ですし、それがタイムリーに行われなければいけないので高度な解析や機械学習の結果が人間以上の結果をもたらすのは難しいでしょう。
(d) 解析結果を専門家以外理解できない
(e) 解析者個人の趣向がどんどん入り込んでしまう
いくら高度な技術を元に結果を導いても、それが周囲に理解されなければ全くもって意味がありません。僕たちエンジニアで怖いことは、無駄に技術を駆使した自己満足の結果をもたらしてしまいがちな事ですし。データは人を説得させるものであっても、それ自身が誰にも理解されずに勝手に一人歩きしてもどうしようもありません。前述したとおり、人間の勘が重要なサービスにおいては人が理解できない事は意味がありません。それによる効果がどれほどなのかも後に判断しにくいですし。
解析者の立ち位置について
それでは僕たちはどのような立ち位置で(役割意識を持って)仕事をしていけば良いのでしょうか?僕の思うところを書きますと、
(A) 解析者は企画者や経営者の意志決定を支援する役割に徹するべき
(B) データに基づいた論理的な理論や根拠を明確に相手に伝える能力が必要
(C) 高度な事をやるよりも素早く、わかりやすい結果を出すことに注力する
(D) 時には解析以外の仕事をするを得ないことを受け入れる
(E) 自社のサービスに対して、誰よりもファンであるべき
(A) 解析者は企画者や経営者の意志決定を支援する役割に徹するべき
僕が解析者としての一番の役割は「企画者・経営者の意志決定を(データの立場から)支援する」ことだと思っています。そしてそれは解析者でしかできない唯一の役割でもあると思います。人間の勘に置き換わる結果や仕組みをもたらすのではなく、人間の勘が最大限に活かせるような情報や結果を提供するのです。そのためにどのような集計や解析をするのかを考え、また企画側と常に距離を近くして、どのような要望があるのかをきちんと理解しておくといったコミュニケーションが重要になると思っています。もちろんエンジニアにも解析の結果をきちんと伝えないといけないですし、どのような記録を、どのような形式で残して欲しいのかを伝えることも重要です。
(B) データに基づいた論理的な理論や根拠を明確に相手に伝える能力が必要
(C) 高度な事をやるよりも素早く、わかりやすい結果を出すことに注力する
そうすると相手にいかにわかりやすく伝えるのかをちゃんと考える必要があります。どのように表にまとめるのか、どのようなグラフを出すのか、それをEXCELで出力するのかWebアプリとして出力するのか…こだわりすぎても問題ですが、社内向けだからと言って手を抜きすぎても問題のように思います。また、出力としてはわかりやすいものにしないといけないですが、結果自身は専門家にしかできない、かつ明確な論理に基づいたものでないといけなません。
(D) 時には解析以外の仕事をするを得ないことを受け入れる
話が少しそれますが、ベンチャーで働く以上、自分の仕事だけに固執するのも良くないと思います。解析という仕事はとても重要ですが、経営が厳しい時には真っ先に切られる仕事でもあると思っています。何より企画し、それを実装してお金にしていく事が最優先で、結果の解析などはどうしても後回しです。実際、多くのベンチャーでまだきちんとログ解析ができていないのもそいういった優先度があるからで、これは仕方の無いことだと思っています。そういった意味では、エンジニアとして開発実装やインフラ回りを兼任できる最低限の能力は必要だと思っていますし、それを受け入れる覚悟も必要だと思っています。そして、そういう仕事であるからこそ、自らの市場価値を高めるための日々の努力はとても重要だと思います。
(F) 「自社のサービスに対して、誰よりもファンであるべき」
この言葉は当時GREEの採用面接に行った時に、データマイニングエンジニア、森さんから聞いた言葉で、今でも非常に心に残っています。企業におけるデータマイニングにおいては、選択(どういうデータや手法を用いるのか)と意志決定(結果から的適切なアクションを起こす)が非常に重要です。そしてそれを適切に見分けるためには、何より解析者自身がサービスに精通していないといけないということです。誰よりもサービスについて知っていなければ良い解析はできません。
最後に
今回もだらだらと長くなってしまいました。おそらく、解析者の立ち位置なんて個々のスキルや会社の規模によって全然変わってくると思います。ただ、その時その時に自分の立ち位置を明確にしておいて仕事をこなしていくのはとても重要なことに感じています。とりわけ、解析者なんて社内では希少種ですし、周囲がせわしなく開発のリリースやバグ処理に追われている中でじっくりログを眺めているなんて時にはうとまれたりしますし、自分の存在価値が問われたりすることは多いと思います。だからこそ、自分はこの会社で解析者として何をもたらすことができるのかを明確に持って、それに向かって全力で取り組む姿勢が重要になってくると個人的には思っています。
まあ、何より僕にとっては今の仕事が楽しくて仕方ありません。また、企画の人からも「こんな数字が見たい」とか、「今日こんなイベントしたけど、どんな感じやった?」みたいに僕に色々意見や要望を言ってくれますし、少なからずデータを重視しようという文化に変わってきましたし、まだまだ自分のやれていることなんて微々たるものですが、しっかりと地に足をつけて取り組めているなと感じています。面白い結果がでればまたブログや勉強会で発信していきたいと思っています。
※データマイニング、特に機械学習については概要を http://labs.gree.jp/blog/2010/09/1310/ にも書かせていただきました。参考になればと思います。
第7回データマイニング+WEB勉強会@東京で発表してきました。「明日から始めるソーシャルアプリのログ解析」
発表者・参加者双方に有意義な勉強会:データマイニング+WEB勉強会@東京
@doryokujinです。9/26(日)に行われました、第7回データマイニング+WEB勉強会@東京で発表してきました。@hamadakoichiさんによるまとめ(発表資料一覧)とTogetterも参考にして下さい。
僕は第6回から参加させていただいていますが、前回に負けじと今回も本当に素晴らしい勉強会でした。
主催者@hamadakoichiさんの創設の思い・目的・進行方針からもわかっていただけますように、発表者と参加者双方が熱い議論を交わしながら進んでいく勉強会です。そんな勉強会に幸運にも発表枠を頂けましたので発表してきました。勉強会の発表はこれが初めてでした。
明日から始めるログ解析1 〜HadoopとMongoDB を活用したソーシャルアプリ解析〜
このエントリーでは、たくさんの方から頂いたフィードバックを元に、発表内容の振り返りを行いたいと思います。
発表の目的
ソーシャルアプリの裏側(ログ解析)の面白さを伝えたい
僕の個人的な気持ちですが、ソーシャルアプリのログ解析は本当におもしろい、そこを伝えたいという気持ちがありました。それはtomiyoichiさんのコメントにありますように、一般のWebのアクセスログ解析の様に「どこのリンクが何回見られた」、「どのリンクからどのリンクに遷移した」といった"ページやセッション"を軸にした解析ではなく、ユーザー1人1人の行動を解析し、「(そのユーザーは)今日誰と何回交流した?」、「今日どんな商品を買った?」、「今日何日ぶりにログインした?」などといった"人の行動"を元に集計・解析を行って、それを元によりユーザーがゲームを楽しんでくれるような戦略を導いていくからです。
ユーザーの行動を解析すること、そして改善の結果がゲームの売り上げやユーザーの満足度にダイレクトに反映されるといったダイナミックさは、ソーシャルアプリならではのものです。今回は具体的な行動ログと解析方法を具体的に提示することで、その面白さを感じて頂ければと思いました。
ノウハウを得るためには外に出て発表して行くしかない
前回のエントリーにも書きましたが、社内1人でログ解析をやっている僕にとっては、外に出て行ってノウハウを発表して、情報やフィードバックを得てこないと、どうしても独りよがりのダメな解析しかできないと考えているからです。そしてそれが自社への貢献につながっていくと思っています。
情報・ノウハウを公開することのリスクの大きさ、その結果得られるメリットの大きさ
今回はかなりの情報を開示しましたが、それは会社自身にとってリスク・メリット双方を天秤にかけた結果の判断でした。そして発表を終えた今でも、たくさんの方からフィードバックを頂き、そこから得たメリットの方が明らかに大きかったと感じています。情報・ノウハウの公開によるリスクとしては
(1) 社員や顧客の個人情報が漏れる、(2) 会社の経営状況が推測される、(3) 社内のノウハウが流出する、(4) 競合他社に真似される、(5) 低レベルな事や誤った情報を公開して会社のイメージを下げる、
のようなものがあって、確かに(1)や(2)はまずいですが、(3)や(4)、(5)に関しては今の解析フェーズではそこまで気にすることないのかなと感じています。そもそも独自のノウハウもあまり蓄積されていませんし、発表した手法もフェーズが変われば変わるでしょうし、真似されるだけの技術があったことに対しては自信が持てますし。
よく「データは宝」と言われ、社外秘としてとても大事に保管されていますが、結局そのまま放置されることの方が多かったりします。「宝の持ち腐れ」とも言いますように何もしないで放置しておくのは非常にもったいないと思っていまして、それならばむしろ外に少し持ち出してさらすことによって、先人から金鉱を探り当てる方法を学んでくる方が僕は重要だと考えています。まあ、この会社自身がベンチャーでしかもとてもオープンな会社で、かつ真似されてもそこに負けないだけの技術力があるという所であったからそれができたのですが。僕はこの会社のそういうところが好きです。
後は、ベンチャー企業が多いこの業界では、ログ解析自身にほとんど着手できないところも多いと思っています。そういった会社が、この発表を聞いて資料を見て、題名の通り明日からログ解析を始めてもらえるきっかけになってもらえれば非常に嬉しい限りです。これが業界の貢献に関するところかな、と。
Hadoopを選んだ理由
今回は行動ログの集計を行うところでHadoopを使用しています。しかしHadoop側でいきなりデイリー指標を集計するといった、すぐにレポートできるくらいのたくさんの処理をやらせるのではなく、レコードの一部分を後で集計しやすい様に整形することと、せいぜいユーザーごとに行動タイプで集計する(頻度やポイントの変化を数える)といった軽い集計しか行わず、しかもHDFS上のファイルとして出力するのではなく、MongoDBに格納して行きます。その時に頂いた意見としましては、
といった、Hadoopの使い方に疑問を持った意見が多かったです。うーん、確かに言われてみればそうかもしれませんねー。少しここは検討してみます。ただ、このようなHadoopの使い方をした理由としましては、元々の設計思想に、
集計作業と解析作業の明確な切り分け
を行いたいというのがあったからです。
解析作業というのは日時単位やユーザー単位である程度集計されて扱いやすくなったデータセットを切り出してきてRやEXCELやKNIMEやRapidMinerなどのツールで解析し、レポートを作る工程で、集計作業というのは散在するログやDBのデータを集約・集計する工程です。そして今後入ってこられる解析者やマーケッターの方々には、集計作業の面倒くさい部分を意識することなく、解析作業に専念して欲しいという想いがありました。
そういった思想を踏まえて考えると、Hadoopでの処理はもちろん集計作業の方ですから、解析専門の人にはここのソースコードをいじったり、大容量のログを何度も読み直すような事はして欲しくありません。今まで見ていなかった指標値が欲しいといった状況があった時は、データバンクからその指標の名前を指定して簡単に取り出せるような仕組みでないといけません。そしてそのデータバンク的存在がMongoDBなんです。なので行動ログだけでなく、MySQLに入っている課金情報やCassandraに入っているユーザーのセーブデータもこのMongoDBに集約しておかないといけなくて、かつ同じ粒度でデータを保存しておかないといけません。それが初めの意見、なぜHadoopに細かい処理をやらせないのか?に対する現状の答えになります。
MongoDBを選んだ理由
ではなぜデータバンクとしてMongoDBを選んだのかという話をしたいと思います。データを一元管理したいという設計思想や、行動ログ解析の性質や社内に解析のノウハウがたまっていないという現状を加味すると、
- スキーマは定義できない:取得する項目がイベントや解析手法変更によって常に増減するので
- 様々な条件で検索できる柔軟さが必要:日時やユーザー、行動タイプ…さまざまな条件で検索できないとダメ
- 更新性能は二の次:柔軟な検索ができる事の方が重要です
- 日常の扱いやすさ:シェル上で簡単な操作ができると嬉しい
といったところの要請を満たして欲しいことになります。そういった要請を満たすデータの管理方法が何か、と考えたときに
- (集計済の)各データをHDFS上のファイルとして管理しておき、HiveやPigでデータを取得する
- MySQLできちんと管理する
- HBaseやCassandraなどの列指向データベースを用いる(NoSQL)
- MongoDBやCouchDBのようなドキュメント指向データベースを用いる(NoSQL)
といった候補の中でMongoDBの採用に行き着きました。選んだ理由ですが、スキーマレスでありながら柔軟な検索機能があること、全てのキーにインデックスが貼れること、出力も検索クエリーにもJSONライクな形式をとっていて直感的に扱えるといったことが挙げられます。MongoDBに至った経緯は様々な資料を参考にし、また色々な試行錯誤があってのものでして、そこのところはまたお話しできたらと思います。
また、MongoDBの性能がどれほどのものか、今回の目的に合致するものとして本当に最適なのか、といったところはきちんとこれから検討しないといけません。また、レプリケーションやシャーディングについても実用性をきちんと検討していかないといけません。そういった所は今後調査・検討してブログのエントリーとして報告していくつもりです。
解析者の立ち位置について
スライド最後に書いた部分ですが、ここで多くの方に共感のコメントを頂けたのは嬉しい限りです。ここの部分も改めてしっかり書きたいと思っていますので、次回以降のエントリーということで宜しくお願いします。
勉強会を振り返って
今回の勉強会も様々な分野からの発表者や参加者が来てくれてとても刺激的な勉強会でした。また同じ業界の@satullyさんや @buhiiさんと深いお話しができたり、苦労を共有できたりして僕にとってはとても貴重な場所になってきました。運営者の@hamadakoichiさんと@yanaokiさん、そして毎回会場を提供していただいているニフティさんには大変感謝しております。本当にありがとうございます。今後ともより良い会を目指して協力していきたいと思います。