MongoDBドキュメントチュートリアル

こんにちは@です。まずは皆さんのおかげでMongoDB JPを立ち上げることができ、かつ150名以上の方に参加していただいている事に感謝したいと思っています。今後積極的な活動を行っていきますのでどうぞ宜しくお願いします。

さて、本エントリーはMongoDB JPの方で日本語ドキュメントを手伝ってくれる方を募集し、かつどの部分を翻訳したいですかと尋ねたところ、「ドキュメントの構成がどうなっているのかわからない」という貴重なご意見を頂きました。確かにおっしゃるとおりでどのようなドキュメントの構成なんてわかりませんよね、しかもそれをすぐに把握するのも大変ですし。そこで今回はドキュメントがどのような構成になっているのか、ドキュメントに沿ってMongoDBの機能を簡単に紹介するようなチュートリアルをやってみたいと思います。そういう意味で全て本家ドキュメントからの引用になります。

なお、前エントリー、MongoDBのちょっと詳しいチュートリアルも参考になると思いますので宜しくお願いします。

※日本語ドキュメント訳には現在10名程度の方が手を挙げて下さっています。本当にありがとうございます。実際の進め方や管理方法、用語の統一など、スムーズな作業ができるようにそちらの環境を整えていきますので宜しくお願いします。もし経験者の方で複数人での訳の進め方について何かアドバイスがございましたらコメントいただけると幸いです。

ドキュメントインデックス

現在のドキュメントの目次は以下のようになっています。本日のアジェンダはこの目次に沿って行きたいと思います。フライングしますが、Aboutのページはあまり読まれなかったりしますが、かなりの情報が詰まっていますので是非とも見落とさずに読んでみて下さいね。

  1. Introduction
  2. Quickstart
  3. Downloads
  4. Drivers
  5. Developer Zone
  6. Admin Zone
  7. Contributors
  8. Community
  9. About
  10. International Docs(省略)
  11. Books
  12. Doc Index(省略)

1. Introduction

まず一番初めに見るべきイントロダクションです。10gen CTOであるEliot Horowitz氏の言葉に始まり、MongoDBの特徴、

  • Document-oriented
  • High performance
  • High availability
  • Rich query language

が簡単に書かれています。箇条書きで詳しく書かれていないのであまり読む必要は無いような気がします。

2. Quickstart

  1. Quickstart OS X
  2. Quickstart Unix
  3. Quickstart Windows

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、@さんの作られたCakePHPといったフレームワークのORMとしてのライブラリも各種充実しています。現在サポートされている言語は、

になっています。さらに最近ではRからMongoDBを呼び出せるRmongomongo-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)

で、推奨ファイルシステムLinux)はext4かxfsとなっています。

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

MySQLphpmyadminのような、UIから直感的にMongoDBを扱えるツールが多数スクリーンショット付きで紹介されています。僕も一通り試してみましたが、結局はシェルで操作するのが一番柔軟で楽なので使わずに終わっています。ただ、管理者以外の複数のメンバーがデータを閲覧できる方法として考えると非常に便利かもしれません。

その他

その他細かい項目がありますが、割愛させて頂きます。

7. Contributors

Contributer向けのルールや加入方法などについて記載されています。肝心のドキュメント翻訳のContributing to the Documentationになっていますが、日本語ドキュメント訳を手伝って下さる方を募集しています。MongoDB JAの募集スレッドからの返信か、僕@に連絡いただければ申請を行いますので是非という方は宜しくお願いします。

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 を立ち上げました!

こんにちは、@です。本日はMongoDB JPの立ち上げに伴って、その告知と本グループにかける想いを少し書かせて頂きたいと思います。まずは改めて、

MongoDB日本ユーザー会:
MongoDB JP
を立ち上げました!興味のある方、ご登録宜しくお願いします!

記念すべき第1回勉強会&懇親会はCouchDB JPの皆様と合同で開催させて頂こうかと思っています。

2010年12月12日(日)
第1回 MongoDB & CouchDB 合同勉強会
※ 開催場所は規模などを見て後日ATNDとメーリングリストで告知します。
※ 現在MongoDBに関する発表者を募集中です。是非とも、という方がいらっしゃれば@ 宛かメーリングリストに連絡宜しくお願いします。

今回の立ち上げに当たってはCouchDB JPの@さんと@さんの温かい支援も頂きました。今後とも情報交換として、また良きライバル(!?)として交流を深めていきたいと思っています。

さて、この告知で大方の目的は果たしましたが、時間のある方は以下のアジェンダでのお話に付き合っていただければ嬉しいです。

  • 設立に至る経緯
  • 目的
  • 活動内容
  • (個人的な)目標

設立に至る経緯

業務でMongoDBを活用してみて

僕自身、MongoDBに出会ったのはつい2ヶ月程前の事です。現在アルバイトをさせてもらっている芸者東京エンターテインメントでの業務、ソーシャルアプリのログ解析(資料1資料2)において散在する各種ログを集計・集積し、かつ解析側が自由にアクセスできるような解析データストレージを検討していたところ、MongoDBに出会い、現在はソーシャルアプリ2種・1TB近くのデータ容量・10億レコード以上を保持し、解析基盤の中枢を担う役割として日々活躍してもらっています。
運用を進めるに当たって感じたことは2点ありまして、

  1. 非常に扱いやすく・高機能で様々なシーンでもっと活用できるはず
  2. 日本ではMongoDBに関する情報が圧倒的に少ない

そしてこのどちらもが今回の設立における原動力となっています。

  • 非常に扱いやすく・高機能で様々なシーンでもっと活用できるはず

実際にログ解析という用途でのMongoDBの運用でも、非常に多くの機能を最大限活用させてもらっています。スキーマレスでありながら豊富なクエリをもち、完全なインデックスをサポートし、かつレプリケーションシャーディングが非常に容易に行え、コンソールから何でも操作できて…そういった機能はログ解析に限らず様々な用途での活用にもベストな選択になりうると感じるようになりました。例えば、

のようなものがMongoDBを使うことでかなり楽にできる気がします。比較的新しいサービスが日本からもドンドンと生まれて来て欲しいなと考えています。

  • 日本ではMongoDBに関する情報が圧倒的に少ない

海外ではfoursquareの利用を始めとして、MongoDBを活用したサービスが多数存在し、かつ本家ユーザーグループでの議論がとても盛んに進んでいます。ただ、現在のところまだ日本ではMongoDBという名前はあまり知られていない現状であり、それ故に日本語の情報がとても少ないです。こういった部分がネックになってさらに利用が遠ざかっていってしまうのはとても残念なことだと思います。
日本からもMongoDBに関する情報をどんどん増やしていって、企業から個人利用に至るまで、誰でももっと気軽にMongoDBに触れるようになったらないいなと思います。さらにこちらからどんどん技術のフィードバックを出していって、MongoDBの開発自身にも貢献していければと思っています。

後は思い切りですよね

日頃業務でも社員の方々には色々MongoDBの話を聞いてもらっていたり、個人的に仲良くしていただいている@さんや@さん、 @さんとMongoな話をしていたりして、ユーザー会を立ち上げてもっとMongoDBの事を知ってほしいな、色んな人に会いたいなと思っていました。
そんな想いが募りに募ってきた頃、ちょうど先日、@さん、@さん、@さんという、PHP界の第一線を走られかつとてもMongoなアツイ方々とお酒を飲む場がありまして、「じゃあやろう!」という話でその場で盛り上がりました。そして@さんのこの強烈な後押しによって、思い切ってその日にTwitterで告知したという経緯になります。ありがたいことに非常に多くの方の反応があり・温かいお言葉をたくさん頂いて、今はなんでもっと早くやらなかったのかと思っています。まあ、本当に大切なのはこれからですからね、頑張ります^^。

目的と活動内容

何よりの目的はMongoDBの日本での普及です。普及という言葉にかける想いは、たくさんのエンジニアが門戸を叩いてくれるような「広がり」という側面と、熱心なエンジニアが議論を交わしあえたり勉強会で交流できるような「深み」を持った側面を持っています。

  • [勉強会]:定期的な勉強会を通じて技術・情報交流を進めていきます。
  • [交流]:CouchDB JPとの積極的な技術・情報交流を行ないます。
  • [ドキュメント]:MongoDB日本語ドキュメントの整備を行ないます。
  • [Q&A]:MongoDB活用に伴う問題・課題をメンバーで議論・解決していきます。
  • [イベント]:MongoDBカンファレンスの日本開催に向けての働きかけを行います。
勉強会

勉強会は積極的に開催していきたいと考えています。また他のNoSQLとの比較や、MongoDBのサービスへの活用事例、Node.jsやWebOSとの連携の話など、他の技術やコミュニティとのコラボレーションなども積極的に行って行きたいと思います。

交流

本家ユーザーグループでは常に積極的な様々議論が行われていますが、こちらでもそういった議論やQ&A、情報交流が活発になり、それが多くの方の有用な情報源となっていく場を目指します。

ドキュメント

MongoDBドキュメントの日本語訳を整備していきたいと思っています。現在の日本語ドキュメント訳は最近僕も参加させて頂いていますが、今のほとんどの部分は@さん1人の貢献に寄るものです。より多くの方々に関わって頂き、ドキュメントの整備を勧めていきたいと思っています。他にも現在出版されているMongoDBに関する本の日本語訳などもできたらと思います。

イベント

これはあくまで個人的な想いですが大きなイベント、特に全国各地で開催されているMongo Conferencesを是非とも日本で開催させたいと思っています。
foursquarebit.lyの中の人を呼んで是非ともお話を聞いてみたい!そのために10genの方々に積極的に働きかけて行きたいと思っています。それは個人的にも英語の勉強の良いモチベーションにもなりますし、頑張ります!あ、協力者も募集してます!

目標

最後に個人的な目標ですが、まずは海外で行われるMongo Conferencesに参加してきて、発表してきたいですねー。そこで色んな人と交流できればもっと色々な事ができそうな気がします!後は外国の方々にも注目されるようなサービスと技術を持った日本企業がProduction Deploymentsとして大々的に掲載されることです。
今まで色んな想いを述べさせて頂きましたが、どれも決して実現不可能なことで無いと確信しています。大事なのは”率先して手を上げること”、まずはその渦の中に飛び込んでいけば案外なんとかなるものですし、本当に困難な事があったときはきっと誰かが助けてくれると信じています。インターネット業界って、そんなステキな世界だと僕は思っています。今後とも率先してMongoDB JPの活動に取り組み、皆様に助けられながら大きくしていければと思っています。どうぞ、宜しくお願いします。

第8回データマイニング+WEB勉強会@東京で発表してきました。「MongoDBとAjaxで作る解析フロントエンド&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などの大規模データ処理技術を使いこなせる能力や各種制約の下で適切なアーキテクチャを構築できる能力で、逆に前者はユーザー支点や多角的に物事を観察できる能力、各種ツールを使いこなせる能力です。ですので解析者がいない企業では、前者はインフラエンジニアが兼任し、後者はマーケティング担当や企画側が兼任することになると思います。もちろんどちらの知識も併せ持つことが重要ですが、もし解析者としてエキスパートになるのならば、どちらの方でそれを目指すのかということを考えていかないといけないかもしれません。解析者というと後者の方をイメージされる方、目指している方が多いかもしれません。僕は前者のバックエンドのほうでエキスパートを目指していきたいなと思っています。そこら辺の話はまた別の機会にしたいなと思っています。

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

MongoDBのレプリケーションとバックアップ機能の紹介

久々の更新です。MongoDBのドキュメントのReplicationの部分の訳が一応完了しましたので、それに合わせてこのブログでもReplication機能について書いていきたいと思います。まだ解釈の甘い部分も残っていますので、今後もこの部分の勉強を続け修正を行っていきます。また、引き続きAdmin Zoneの訳を進めていくつもりです。
本日のアジェンダです:

  1. MongoDBのReplication機能について
    1. Master/Slave
    2. Replica pair
    3. Replica set
  2. MongoDBのバックアップ機能について
    1. ファイルのバックアップ
    2. 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として動作することになります。しかし書き込みが双方のサーバーで継続して可能な場合、この状況ではデータの競合が起こってしまいます。


f:id:doryokujin:20101102053703p:image
arbiterサーバーが必要となる場合。通信障害の後もClientsからのリクエストは双方のサーバーへ届いてしまいます。
これを防止するためにarbiterサーバーがただ1つの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の選ばれ方についてはまだ理解が浅く、もしかしたら上の記述は間違っているかもしれません(すいません)。その際はご指摘していただけると幸いです。


f:id:doryokujin:20101102070754p:image
primaryがダウン。この時secondary2が1分前に同期を終えたばかりで最新のデータを有している。


f:id:doryokujin:20101102070755p:image
この時secondary2が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

こんにちは、@です。前回に引き続き、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)

さらに多くの情報は公式ドキュメント日本語訳の地理空間のインデックスを参照してください。

参考:Foursquare & MongoDB

サービスダウン時の状況

  • 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のすべてのサービスは完全にダウンしてしまっていました。

参考:So, that was a bummer.

本当に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のデザインやトラブル対応に少し不備があったのではと考えるほうが自然になります。

参考:MongoDB, FourSquare and the Sharding problem

サービスダウンの引き金となった出来事

foursqareではサービスダウン当時、AmazonEC2上で66GBのメモリを積んだ2台のマシンでシャーディング(データベースを分割することで負荷やディスク・メモリ容量を分散させる方法)を行なっていました。シャーディングはユーザーIDを元に行われていました。それまでの2ヶ月間の運用では、データは2台のサーバーに均等にうまく振り分けられていてどちらのシャードも約33GBのメモリを消費する程度で安定していました。しかし今回はこのバランスが崩れてしまったようで、サービスダウンの原因は

  • 1. 片方のシャード(shard0とする)のメモリが物理限界の66GBをオーバーし、著しい性能低下を引き起こした

であったと報告されています。さらにその対策もうまくいかなかったわけで、

  • 2. 第3のシャードを追加することによってshard0から5%のチャンク(データの塊)を移行しようとしたが、その後もshard0のメモリ容量が減らず、状況が解決されなかった

ために、復旧に11時間もかかってしまいました。しかし、幸いにも一部のデータが失われるといった状況にはなりませんでした。

参考:Foursquare outage post mortem

本質的な原因はどこにあったのか

それではこれに関する本質的な原因をMongoDBの特徴と絡めて詳しく見ていくことにします。まず前者に関しては、

ユーザーIDをキーにした分割方法が適切でなかった

が考えられます。ちなみにもう片方のサーバーのメモリ消費量は50GBでした。ユーザーIDを分割のキーとしていたために、片方のシャードに何度もチェックインを繰り返すヘビーユーザーが偏ってしまう振り分けになってしまっていたとしたら、このような状況になってしまう可能性があります。また、後者の原因にはMongoDBが密接に絡んでおり、

インデックスに使用したメモリの断片化によってshard0の負荷を低減させることに手間取った

ことが考えられます。foursquareが記録していたチェックインに関するレコードは1レコード当たり約300バイトでしかありませんでした。実はMongoDBでは4KB以下のレコードの集合に関しては、それが別のシャードに移動したり削除されたとしてもインデックス作成に使用された一部のメモリは開放ずに残ってしまう(断片化)状況が起こってしまうのです。foursquareの場合は、データが連続しているチャンクから効率よくデータを移行することができずにこの状況が起こってしまいました。user-groupのDetails on FourSquare bug?において、新しいシャードの追加が素早く・効果的に機能するための条件として、Dwight Merriman (10gen)は以下のように述べています:

  1. シャードの条件に設定されたキーの振り分けが挿入順序で行われる場合
  2. ソースとなるシャード(ここではshard0)に高負荷がまだかかっていない状況時にシャードを追加した場合
  3. 1つ1つのレコードが4kBより少し上回る程度の容量を持っている場合
  • もしこれらの条件のすべてを満たしていない場合は、速やかにデフラグを行い、断片化の進行を防ぐ必要がある

同サイトに、4kBより遥かに小さい大量のレコードで構成されたコレクションを作成して検証が行われています。このコレクションはインデックスに約300MBの容量を消費していましたが、このコレクションを削除したあとも2.3MBの容量を消費していることがわかります。さらにこのコレクションを作成しては削除するといった動作を繰り返すたびに、どんどん消費量が増えていっています。今回のケースでもこの断片化が引き起こされていたことが考えられます。さらに、他の2条件も満たしていなかったので、なかなか追加シャードへのデータの移行が進みませんでした。

参考:Details on FourSquare bug?

復旧後の状況

その後shard0の復旧が進み、また3番目のシャードに一部のデータの移行が完了したために、現在はデータが均等に振り分けられ安定に動作していると報告されています。MongoDBには全てのインデックスを再構築するためのrepairDatabase()コマンドがあり、これを実行したようです。このコマンドは、すべてのデータが壊れていなかチェックし、壊れているものがあった場合取り除きます。またデータファイルを少し縮小します。しかし、容量の小さなチェックインレコードを大量に持ったコレクションによって引き起こされた断片化の問題に関しては本質的な解決には至らず、スレーブサーバーに repairDatabase() というコマンド(すべてのインデックスの再生成)を実行して最適化した後、このスレーブをマスターに昇格させることで約20GBの消費に抑えたと報告されています。また、今回明確となったMongoDBのボトルネックは、現在10genの技術チームが解決に向けて取り組んでいるとのことです。

参考(MongoDBのrepairコマンドについて):耐障害性と修復(公式ドキュメント邦訳)
参考(MongoDBのインデックスについて):インデックス(公式ドキュメント邦訳)

foursquareの行なった対策について

今回11時間にも及ぶサービスダウンはユーザーに対しての信頼を損ねてしまう結果になってしまいましたが、やはり新しい技術を使用する以上はこのようなリスクは避けられないと思います。しかし、foursqareはこのダウンの間、

  • サーバーダウン中やバックアップ中である旨のメッセージをTwitterアカウント、 @4sqsupport と @foursquare が伝えた
  • また、 @4sqsupport は毎時間ごとに定期的に状況報告を続けた

ときちんと状況報告に努め、かつこの事例から学んだことを、

  • サービスの稼働状況を表示するサイト、 status.foursquare.comを新たに作成した
  • より意味のあるエラーページを作成することにした。現在どのような状況でそれが起きているのかを詳細に記述するようにした

としてすぐにサービスに反映しました。僕はこの一連のきちんとした対応には好感を持っています。また、この大きな出来事を元にMongoDBがより良いものに、そして他の企業この事例を学んで同じ状況が起こるのを回避できるようになっていくことを願っています。

終わりに

今回、様々な海外サイトを参考にさせていただきましたが、英語面・技術面ともにまだまだ未熟ですので訳や解釈の違いが多々あると思います、その場合はご指摘していただけると幸いです。今回はMongoDBの少しネガティブな部分を書きましたが、他にも色々とネガティブな部分があることがわかっています。MongoDBのメリット/デメリットという軸でそのうちエントリーが書けたらなと思っています。

追記(10/21更新)

後日InfoQより詳細な報告があげられていましたので追記してお伝えします:

InfoQ Foursquare's MongoDB Outage

また、この日本語訳も公開されていますので参考にしてください。

FoursquareのMongoDBが機能停止

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

@です。本エントリーから数回にわけてMongoDBの紹介をつらつら書いていきたいと思います。日々、MongoDBの魅力にどっぷりな僕でして、それを少しでも多くの方に共有できたらというモチベーションで書いています。今回はチュートリアルとして主要な機能を少し詳しめに紹介していきます。アジェンダは以下の通りです:

  • はじめに
  • ちょっと詳しいチュートリアル
    • オープンソース
    • NoSQL・ドキュメント指向データベース
    • ドライバとして多くの言語サポート
    • 完全なインデックスサポート
    • リッチなクエリー
    • MySQLに類似した機能群
    • レプリケーション機能
    • オートシャーディング
    • 巨大ファイルを扱うGridFS
  • 今後の予定
    • 本家ドキュメントの翻訳
    • より深い機能説明
    • 勉強会での発表
    • Production Deploymentsとして弊社の名前を掲載する

はじめに

僕は現在MongoDBをソーシャルアプリのログ解析の中間集計データの格納・集約場所としてMongoDBを活用させてもらっています。MongoDB採用に至る経緯や使用目的については前々回のエントリースライドをご覧頂ければと思います。現在過去3ヶ月の行動ログや課金データなどの集計データのMongoDBへの格納がほぼ完了したところでして、現在約2億件のレコードが、シャーディングされた3台のマシンで管理しています。今後は実際のデータ解析を行いながら経営や企画の方々にデータの側から様々な提言をしていきたいと思っています。と、同時に誰でも簡単にデータを閲覧できるようなフロント部分の実装(Webアプリ)も進めて行く予定です。MongoDBにはmongooseというJavaScriptからMongoDBにアクセスできる非常に便利なライブラリーがありますので、これとテーブルや描画関連のAjaxを利用しながら効率よく作業を進めていく予定です。相関を求めたりモデル式を作成したりといった少し突っ込んだ解析にはRに全部任せてしまおうと考えています。このように、芸者東京エンターテインメント GTEにおいて、MongoDBはソーシャルアプリのログ解析のバックエンドとフロントエンドをつなぐ非常に重要な役割を担う存在となっています。

f:id:doryokujin:20101010053256p:image
おみせやさんのログ解析

業務でのアプリケーションや実際のパフォーマンスにつきましては次回のデータマイニング+WEB 勉強会@東京 #TokyoWebMiningで発表させて頂きたいと思います。(次回は11月14日予定です。是非ともご参加下さい!アジェンダはこちらです。)

ちょっと詳しいチュートリアル

それではMongoDBとは一体どのようなDBなのか、今回は主に公式ドキュメントを参照しながら少し突っ込んだ形のチュートリアルとてして見ていきたいと思います。参考にした資料、詳しく書かれた資料などは随時リンクを張っていきます。

オープンソース

現在MongoDBは開発・サポート元である10genからオープンソースとして公開されています。彼らによって商用サポートも行われているみたいです。また、素晴らしいことに公式ドキュメントが非常に充実しています。公式ドキュメントの日本語訳もかなり進んでいます。この日本語ドキュメントは全て@さん1人の手によって運営されています。(ブログはこちら)@さんの日本語訳によってたくさんの方が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, C++, Java, Javascript, Perl, PHP, Python, Ruby

ですが、コミュニティサポートとして

C# and .NET, Clojure, ColdFusion, Erlang, Go, Groovy, Haskell, Javascript, Lua, Objective C, Scala, etc...

など、非常に充実しています。

Rails

さらにWebアプリケーションフレームワークのModelとしてMongoDBを扱うためのライブラリも用意されています。例えばRuby On Railsここに詳しく書かれていたり、企業のRails+MongoDB活用事例としては、

が参考になると思います。

Python+Django

僕はPythonを利用してMongoDBの操作を行っています。ドライバは2種類、

を確認しています。僕は前者のPymongoを使用しています。後者はまだ試した事がありませんので比較はしていませんが併せてDjango-MongoKitも用意されているので、Djangoまでの使用を考えるとこちらを使う方が一貫性があって良さそうです。その他のDjangoのサポートとして

があるみたいです。僕も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コマンドを紹介していますが、これだけで簡単にレプリケーションが行えるという事を理解してもらいと思ったからです。

  1. Master/Slave
  2. Replica Pairs
  3. Replica Sets

◆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という記事を翻訳してみたいと思っています。

本家ドキュメントの翻訳

現在の日本語ドキュメントを作成していただいている@さんに協力する形で、今後僕も公式ドキュメントのAdmin Zoneの部分の残りの訳を担当させて頂くことになりました。現在のような質の高いドキュメントを維持できるかは不安ですが、皆さんのお役に立てる事を信じて、しっかりと訳を進めていきたいと思います。進捗はブログやTwitter等で告知していきたいと思っています。

勉強会での発表

今後とも勉強会には積極的に参加して、発表を通じて多くの方と議論をしていければと思っています。こちらは主に、現在仕事で行っている、「ソーシャルアプリのログ解析での(アプリケーションとしての)MongoDB」という位置づけで、前回に引き続き、リアルな話をしていきたいと思っています。

Production Deploymentsとして弊社の名前を掲載する

これは実は自分の中で大きな目標にしているのですが、MongoDBの公式サイトのProduction Deploymentsにソーシャルアプリでの導入事例として日本企業初として芸者東京エンターテインメントの名前を是非とも連ねたいですね…はい。

また、このサイトは他の企業がどのような用途でMongoDBを導入しているかという、非常に参考になる部分が多いページですので、ぜひともこのサイトの翻訳と各社の事例紹介を行っていきたいと思っています。

「解析者の立ち位置」について僕が思うこと。

こんにちは、 @ です。週に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勉強会@東京

@です。9/26(日)に行われました、第7回データマイニング+WEB勉強会@東京で発表してきました。@さんによるまとめ(発表資料一覧)とTogetterも参考にして下さい。

僕は第6回から参加させていただいていますが、前回に負けじと今回も本当に素晴らしい勉強会でした。
主催者@さんの創設の思い・目的・進行方針からもわかっていただけますように、発表者と参加者双方が熱い議論を交わしながら進んでいく勉強会です。そんな勉強会に幸運にも発表枠を頂けましたので発表してきました。勉強会の発表はこれが初めてでした。


明日から始めるログ解析1 〜HadoopとMongoDB を活用したソーシャルアプリ解析〜

このエントリーでは、たくさんの方から頂いたフィードバックを元に、発表内容の振り返りを行いたいと思います。

発表の目的

ソーシャルアプリの裏側(ログ解析)の面白さを伝えたい

僕の個人的な気持ちですが、ソーシャルアプリのログ解析は本当におもしろい、そこを伝えたいという気持ちがありました。それはtomiyoichiさんのコメントにありますように、一般のWebのアクセスログ解析の様に「どこのリンクが何回見られた」、「どのリンクからどのリンクに遷移した」といった"ページやセッション"を軸にした解析ではなく、ユーザー1人1人の行動を解析し、「(そのユーザーは)今日誰と何回交流した?」、「今日どんな商品を買った?」、「今日何日ぶりにログインした?」などといった"人の行動"を元に集計・解析を行って、それを元によりユーザーがゲームを楽しんでくれるような戦略を導いていくからです。

ユーザーの行動を解析すること、そして改善の結果がゲームの売り上げやユーザーの満足度にダイレクトに反映されるといったダイナミックさは、ソーシャルアプリならではのものです。今回は具体的な行動ログと解析方法を具体的に提示することで、その面白さを感じて頂ければと思いました。

ノウハウを得るためには外に出て発表して行くしかない

前回のエントリーにも書きましたが、社内1人でログ解析をやっている僕にとっては、外に出て行ってノウハウを発表して、情報やフィードバックを得てこないと、どうしても独りよがりのダメな解析しかできないと考えているからです。そしてそれが自社への貢献につながっていくと思っています。

情報・ノウハウを公開することのリスクの大きさ、その結果得られるメリットの大きさ

今回はかなりの情報を開示しましたが、それは会社自身にとってリスク・メリット双方を天秤にかけた結果の判断でした。そして発表を終えた今でも、たくさんの方からフィードバックを頂き、そこから得たメリットの方が明らかに大きかったと感じています。情報・ノウハウの公開によるリスクとしては

(1) 社員や顧客の個人情報が漏れる、(2) 会社の経営状況が推測される、(3) 社内のノウハウが流出する、(4) 競合他社に真似される、(5) 低レベルな事や誤った情報を公開して会社のイメージを下げる、

のようなものがあって、確かに(1)や(2)はまずいですが、(3)や(4)、(5)に関しては今の解析フェーズではそこまで気にすることないのかなと感じています。そもそも独自のノウハウもあまり蓄積されていませんし、発表した手法もフェーズが変われば変わるでしょうし、真似されるだけの技術があったことに対しては自信が持てますし。

よく「データは宝」と言われ、社外秘としてとても大事に保管されていますが、結局そのまま放置されることの方が多かったりします。「宝の持ち腐れ」とも言いますように何もしないで放置しておくのは非常にもったいないと思っていまして、それならばむしろ外に少し持ち出してさらすことによって、先人から金鉱を探り当てる方法を学んでくる方が僕は重要だと考えています。まあ、この会社自身がベンチャーでしかもとてもオープンな会社で、かつ真似されてもそこに負けないだけの技術力があるという所であったからそれができたのですが。僕はこの会社のそういうところが好きです。

後は、ベンチャー企業が多いこの業界では、ログ解析自身にほとんど着手できないところも多いと思っています。そういった会社が、この発表を聞いて資料を見て、題名の通り明日からログ解析を始めてもらえるきっかけになってもらえれば非常に嬉しい限りです。これが業界の貢献に関するところかな、と。

Hadoopを選んだ理由

今回は行動ログの集計を行うところでHadoopを使用しています。しかしHadoop側でいきなりデイリー指標を集計するといった、すぐにレポートできるくらいのたくさんの処理をやらせるのではなく、レコードの一部分を後で集計しやすい様に整形することと、せいぜいユーザーごとに行動タイプで集計する(頻度やポイントの変化を数える)といった軽い集計しか行わず、しかもHDFS上のファイルとして出力するのではなく、MongoDBに格納して行きます。その時に頂いた意見としましては、

  1. なぜHadoopでもっと細かい処理をやらせないのか
  2. 本当にHadoopを使用する意味があるのか。MongoDBに直接集計値を挿入すれば良い

といった、Hadoopの使い方に疑問を持った意見が多かったです。うーん、確かに言われてみればそうかもしれませんねー。少しここは検討してみます。ただ、このようなHadoopの使い方をした理由としましては、元々の設計思想に、

集計作業と解析作業の明確な切り分け

を行いたいというのがあったからです。

解析作業というのは日時単位やユーザー単位である程度集計されて扱いやすくなったデータセットを切り出してきてREXCELKNIMERapidMinerなどのツールで解析し、レポートを作る工程で、集計作業というのは散在するログやDBのデータを集約・集計する工程です。そして今後入ってこられる解析者やマーケッターの方々には、集計作業の面倒くさい部分を意識することなく、解析作業に専念して欲しいという想いがありました。

そういった思想を踏まえて考えると、Hadoopでの処理はもちろん集計作業の方ですから、解析専門の人にはここのソースコードをいじったり、大容量のログを何度も読み直すような事はして欲しくありません。今まで見ていなかった指標値が欲しいといった状況があった時は、データバンクからその指標の名前を指定して簡単に取り出せるような仕組みでないといけません。そしてそのデータバンク的存在がMongoDBなんです。なので行動ログだけでなく、MySQLに入っている課金情報やCassandraに入っているユーザーのセーブデータもこのMongoDBに集約しておかないといけなくて、かつ同じ粒度でデータを保存しておかないといけません。それが初めの意見、なぜHadoopに細かい処理をやらせないのか?に対する現状の答えになります。

データクリーニング機能としてのHadoop

ただ、1日4GBの行動ログをそのままMongoDBに入れていくといずれパンクしますし、ログの中には不要な情報もありますし、解析ノウハウが貯まってくるにつれて必要のない指標がどんどんわかってくると思います。そういったものを事前に排除して1/10位にサイズダウンさせるためのFilterとしてのHadoop活用も見込んでいます。また、今後より大きくなっていくログを想定してもHadoopで何らかの処理を行うという仕組みは初めから作って残しておきたかったというのもあります。それが2番目の意見に対する理由です。

MongoDBを選んだ理由

ではなぜデータバンクとしてMongoDBを選んだのかという話をしたいと思います。データを一元管理したいという設計思想や、行動ログ解析の性質や社内に解析のノウハウがたまっていないという現状を加味すると、

  • スキーマは定義できない:取得する項目がイベントや解析手法変更によって常に増減するので
  • 様々な条件で検索できる柔軟さが必要:日時やユーザー、行動タイプ…さまざまな条件で検索できないとダメ
  • 更新性能は二の次:柔軟な検索ができる事の方が重要です
  • 日常の扱いやすさ:シェル上で簡単な操作ができると嬉しい

といったところの要請を満たして欲しいことになります。そういった要請を満たすデータの管理方法が何か、と考えたときに

  • (集計済の)各データをHDFS上のファイルとして管理しておき、HiveやPigでデータを取得する
  • MySQLできちんと管理する
  • HBaseやCassandraなどの列指向データベースを用いる(NoSQL)
  • MongoDBやCouchDBのようなドキュメント指向データベースを用いる(NoSQL)

といった候補の中でMongoDBの採用に行き着きました。選んだ理由ですが、スキーマレスでありながら柔軟な検索機能があること、全てのキーにインデックスが貼れること、出力も検索クエリーにもJSONライクな形式をとっていて直感的に扱えるといったことが挙げられます。MongoDBに至った経緯は様々な資料を参考にし、また色々な試行錯誤があってのものでして、そこのところはまたお話しできたらと思います。

また、MongoDBの性能がどれほどのものか、今回の目的に合致するものとして本当に最適なのか、といったところはきちんとこれから検討しないといけません。また、レプリケーションやシャーディングについても実用性をきちんと検討していかないといけません。そういった所は今後調査・検討してブログのエントリーとして報告していくつもりです。

解析者の立ち位置について

スライド最後に書いた部分ですが、ここで多くの方に共感のコメントを頂けたのは嬉しい限りです。ここの部分も改めてしっかり書きたいと思っていますので、次回以降のエントリーということで宜しくお願いします。

勉強会を振り返って

今回の勉強会も様々な分野からの発表者や参加者が来てくれてとても刺激的な勉強会でした。また同じ業界の@さんや @さんと深いお話しができたり、苦労を共有できたりして僕にとってはとても貴重な場所になってきました。運営者の@さんと@さん、そして毎回会場を提供していただいているニフティさんには大変感謝しております。本当にありがとうございます。今後ともより良い会を目指して協力していきたいと思います。

勉強会での発表の大切さ ー僕が勉強会で発表した理由ー

こんにちは、@です。Twitterの方にべったりの僕ですが、今更ながらブログも始めました。

もともと勉強会で何か発表したらブログを始めようと思っていましたので僕の中では自然な流れではありました。本日は初エントリーなので、なぜ勉強会で発表しようと思ったか、そしてそれと同時になぜブログを始めたかをつらつらと書いていきたいと思います。その前に今の自分の背景を説明します。こういう環境で働いているからこそ、勉強会で発表することが重要だと考えるようになったんです。

ベンチャーでの働き方について

僕は今、アルバイトで芸者東京エンターテインメント GTE というwebベンチャーでログ解析チーム(といっても僕1人ですが)として、ソーシャルアプリ「おみせやさん」を初めとしたサービスのログ解析を行っています。ちょうど今2ヶ月経ったくらいでしょうか。GTEでは今までログ解析を行っていなかったので、ログ解析に関するノウハウなど無く、僕が解析ノウハウを生み出し、蓄積していく立場にあります。なので環境構築からプログラム実装、そして解析手法確立のところまで、解析に関わる全ての部分を自分で考え、作り出していかないといけません。

あっ、僕はこの環境を嘆いているわけではなく、むしろとても幸せに感じています。自分がパイオニアとしてやりたいようにできますし(責任もその分大きいですが)、社内の優秀なエンジニアの先輩方が技術面では全力でサポートしてくれますし、とても恵まれたPC環境を与えてもらっていますし、人の2倍くらいの成長できる内容でありますし、会社のメンバーも大好きですし、むしろ仕事が楽しくて仕方ありません。

どうやって作業を進めていくか

話は戻りますが、そういった環境の中できちんとした技術やノウハウを確立して、会社に蓄積し経営に貢献していくためには外にいる先人の知恵に頼るしかありません。そのための最も便利で手軽な方法はGoogle先生で、様々なブログや技術サイトからノウハウを頂いてきて自分のところに移植していきます。以前「ググるな危険(元ソースはこれ?)」とかいって話題になりましたが、少なくとも僕はググらないと死にます。何もできません。もちろん、「1つのサイトだけを信用しない」「本家サイト(英語)を嫌わない」など僕なりに色々注意しているところはありますが…

  • コミュニティに聞く

あとはそれでもわからないことは、コミュニティに聞いてみることも重要だと考えています。人に伝えるための文章にして質問を投げかけることは、改めて自分の抱えている問題を整理するきっかけにもなりますし、もしそれが海外コミュニティであれば英作文の練習にもなります。例えば僕は社内でKNIMEという解析ツールの使用を検討しているところです。それほど有名なツール(特に日本では)では無いので検索から得られる情報は皆無で、もしコミュニティを利用しなければ、エラーでつまづいた時はソースコードを読んでなんとかするしかありませんし、「KNIMEのバッチ処理で画像の出力先って指定できるの?」「MongoDBのKNIME用jdbcアダプタってまだ無いの?使えるの?」みたいな疑問にはなす術がなかったりします。しかしKNIMEでは本家サイトのコミュニティKNIMEtechがとても手厚くて、Forumに質問トピックを立てると中の人や海外エンジニアの方々がすぐに適切な答えを返してくれます。もちろん、ギブ&テイクの精神は重要で、自分もわかる範囲で質問に対する答えを書き込ませてもらっています。

「おれおれ仕様」に満足しないために

そうやってGoogleやコミュニティの恩恵を受けて、自力でもある程度のプロトタイプは作れます。しかし本当に重要なのはここからで、それが目指すゴールに対して、本当にベストなのか?ボトルネックは無いのか?安定運用できるのか?よりよい代替え技術は無いのか?…そういった部分を再確認しないといけません。そしてここは自分自身ではなかなか知り得る事ができず、それなりに動く「おれおれ仕様」に満足して本格運用を始めたりしがちです。そいういった過ちを防ぐのが「勉強会で発表してフィードバックをもらうこと」だと考えています。

勉強会での発表の大切さ ー僕が勉強会で発表した理由ー

勉強会発表で得られること

勉強会で発表すると、出席者の方やustを見た人からたくさんのフィードバックを頂くことができ
ます。自分自身や所属する企業の技術アピールにもなります。もちろん批判も多数あると思いますが、それも含めて発表者側にとってはとてもとても貴重な情報になります。そしてフィードバックを通じて

  • 自分の使用した方法の妥当性が確認できる
  • 気付かなかった新手法や新技術の発見できる
  • 他社の事例や参考サイトを知ることができる
  • 社外に技術相談役ができる

など、様々なメリットを得ることができます。僕たちベンチャーのエンジニアはこういったフィードバックを最大限に活かして、自社のサービスやノウハウを向上させていくことが不可欠だと考えています。しかし、発表がただ自己アピールしたいだけの内容であったり、聞く人に何のメリットにもならないようなものですと、こういったものは得られません。

発表者の伝えるということへのこだわりと、自分の情報やノウハウをどれだけ公開するかで、フィードバックの大きさは変わってくる

多くの人から有用なフィードバックを得るためには発表者側の努力は不可欠で、当たり前ですが

  • 相手に伝えるための努力

はとても重要です。発表の構成をどうするか、どういう資料にするか、うまくしゃべるにはどうしたらいいかといった所に気を配らないと、そもそも相手に自分が何をやっているのかが伝わりません。でもそこは時間的にもスキル的にも難しいところですよね。恥ずかしながら僕もまだ全然できていません。

そして、これと同じくらい重要なことに、

  • 自分の持っている情報・ノウハウをどれだけ公開するか

という部分が挙げられると思います。これはあくまで僕の立場での話なのですが、自分が持っている情報やノウハウを開示するリスクの大きさよりも、それによって得られるフィードバックの方が大きいと思っています。この辺の話は次エントリーで実際に公開した資料とともに述べさせていただきたいと思います。

どの勉強会で発表するか

これも重要かもしれません。せっかく準備してノウハウ開示して発表しても、会の趣旨と異なっていたり周囲の求める内容と違っていたり、懇親会目当てで発表を誰も聞いていない、といった状況では残念ながら得られるものはそれほど多くありません。僕のような「技術的なアドバイスを頂きたい」という目的で発表する場合は、発表者だけがしゃべるのではなく、参加者と多くの議論ができる・質問が絶えず飛び交うといった双方向の勉強会の方が合っています。今回僕が発表させてもらったデータマイニング+WEB 勉強会@東京ハッシュタグ:#TokyoWebmining)はまさに僕の求めていた勉強会で、発表と議論の時間が半分半分に設定されていて、熱い議論が絶えず、双方共に大変有意義な時間を過ごすことができます。この勉強会に対する主催者hamadakoichiさんの創設の思い・目的・進行方針はこちらから感じていただけたらと思います。

勉強会は家に帰っても勉強会 ーブログでその後の進捗を報告したいー

さて、ではなぜ勉強会での発表と同時にブログを始めたのかというと、僕は「勉強会はうちに帰っても勉強会」だと考えていて、多くの人から頂いたフィードバックをきちんと業務に反映したり、さらに技術を深めていくということを可能な限りやるべきだと思っています。そしてそれをフィードバックしてくれた人に見てもらう、あるいは自分がそれをサボらないために、ブログのエントリーとしてその後の進捗を公開していくという方法がベストだと考えました。ですので勉強会で発表すればすぐにその資料はここでも公開し、そしてその後フィードバッグからどう改善していったかをエントリーとして公開していきたいと思っています。ですのでブログの話題が途切れないためにも勉強会で発表し続けますし、そのために日々の努力をします。後は技術に関する調査結果やインストールメモ、使用した感想などのエントリーもちょくちょく残していきたいと思います。

ということでこれからも宜しくお願いします。次のエントリーはこちらです。