Upload
takahiro-inoue
View
55.650
Download
12
Embed Size (px)
DESCRIPTION
Citation preview
MongoDBを用いたソーシャルゕプリのログ解析
〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜
doryokujin
第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyo
自己紹介• [自己紹介]
▶ いのうえ たかひろ( twitter: doryokujin )
▶ 福沢諭吉大学院2年、数学科 25歳
▶ マラソンも好き(ベスト2時間33分)
• [活動]
▶ MongoDB JP 主催者、ドキュメント訳者
▶ ブログ
▶ 芸者東京エンターテンメント GTE
▶ ゕルバト4ヶ月目、ログ解析部隊(1人)
本日のゕジェンダ
1. ログ解析と MongoDB
▶ なぜ MongoDB を採用したか
2. ソーシャルゕプリのログ解析
▶ 解析バックエンドとフロントエンドでの MongoDB 活用例
3. MongoDB その他のトレンド
▶ MongoDB の先進的な活用事例:Logging、Hadoop、Graph
1. ログ解析とMongoDB
ソーシャルゲームのログ解析〜GTEの場合〜
• [目的] (もちろん会社によって様々)
‣ 今まで出ていた基本的なデータより、もっと細かく多くのデータを提供する
‣ 明確に取得して見たいデータに加えて、あらゆるデータをとりあえず色々見てみる
‣ 解析のバックエンド(後述)からフロントエンドまでを1人でやる
‣ 解析の結果自身が意志決定を行うのでは無く(機械学習・高度な統計は不必要)、人間の意志決定を支援するための結果を出す
解析バックエンドとフロントエンド
‣ 一言に解析の仕事と言ってもバックエンドとフロントエンドで全く異なる仕事になる
‣ 散在するログの収集に始まり、ゕナリスト(フロントエンド)がいつでも所望のデータを取り出せるように適切な形式・場所に格納するための基盤を構築するのがバックエンド
‣ 解析ツールを駆使し、また様々な視点でデータを解析し、人間の意志決定を支援するための結果を導くのがフロントエンド
‣ バックエンドはンフラ、大規模分散処理技術・DB(RDB・NoSQL)の知識が必要。規模や目的に合わせた設計が重要。とても泥臭い仕事
‣ フロントエンドの解析者はいつでもデータが取り出せるという前提のもと、バックエンドを気にせず解析に専念できる状況を想定している
ソーシャルゲームの行動ログ
• [行動ログ]
‣ 個々のユーザーの行動を詳細に知ることができる
‣ ユーザーの行動をいつ・何を・どのような形式でログに出力するのかは開発側が判断・決定
• [出力例]
‣ ログンした
‣ スタミナが 100 回復した
‣ ユーザー A のおみせからゕテム I を勝った
‣ ユーザー B に勝ってゕテム J をゲット
‣ ユーザー C の掲示板に書き込んだ
ソーシャルゲームの行動ログ
• [行動ログの例]
行動のタイプユーザーID 行動の詳細
• [行動ログ詳細]
-----Change------
ActionLogger a{ChangeP} (Point,1371,1383)
ActionLogger a{ChangeP} (Point,2373,2423)
------Get------
ActionLogger a{GetMaterial} (syouhinnomoto,0,-1)
ActionLogger a{GetMaterial} usesyouhinnomoto
ActionLogger a{GetMaterial} (omotyanomotoPRO,1,6)
-----Trade-----ActionLogger a{Trade} buy 3 itigoke-kis from gree.jp:00000 #逆からみれば売った事に
-----Make-----
ActionLogger a{Make} make item kuronekono_n
ActionLogger a{MakeSelect} make item syouhinnomoto
ActionLogger a{MakeSelect} (syouhinnomoto,0,1)
-----PutOn/Off-----
ActionLogger a{PutOff} put off 1 ksuteras
ActionLogger a{PutOn} put 1 burokkus @2500
-----Clear/Clean-----
ActionLogger a{ClearLuckyStar} Clear LuckyItem_1 4 times
-----Gatcha-----ActionLogger a{Gacha} Play gacha with first free play:わくわくおみせ服ガチャActionLogger a{Gacha} Play gacha:わくわくおみせ服ガチャ
行動タプ[actionType]
行動の詳細[actionDetail]
※行動の詳細の値は様々:頻度・変化・対象・複合要素
※行動タプごとに適切な整形が必要
ソーシャルゲームの行動ログ
ソーシャルゲームのログ解析• [行動ログ解析で重要なこと]
‣ どの項目が関係し合っていて、また後で重要になるかがわからないので全て取得しておきたい
‣ そのため解析過程において、ログの持つ情報や構造が失われないことが重要
‣ 集約したログの情報を一元管理するデータサーバーが必要
• [解析データサーバー]
‣ ログから情報を抽出し、それを格納しておく仕組み
‣ 格納場所はDB・HDFS・デゖレクトリ(フゔル)等…
‣ 蓄積された解析データはゕナリスト(フロントエンド)が取り出して解析を行う
ランキング課金情報登録日
解析データサーバー
行動ログ
アクセスログ
各種ログ�������
ゲームセーブ
データ
解析
可視化
解析データサーバー
バックエンド フロントエンド
情報量や構造を失わないように
解析対象となるデータは全て解析データサーバーに
ランキング課金情報登録日
解析バックエンド for GTE
行動ログアクセスロ
グ
ゲームセーブ
データ
MySQLCassandra
Dumbo (Python + Hadoop )整形・フゖルタリング・簡易集計
全集計結果はMongoDBに格納
Python Script
整形・集計データ
scribe でローカルのHDFS上に格納
Thrift & PHP(API)
解析フロントエンド
Sharding×3Replica Set×3
Server× 3
データセンター(ホステゖング
解析フロントエンド for GTE
Sleepy.Mongoose
解析対象データ
GraphDB
WebUI
解析ツール
ソーシャルデータゕクセスログ(遷移データ)
最適な解析データサーバーとは?
工程・時間
情報量
DB:SQL、NoSQLフゔル群:NFS、HDFS
各種ログ
解析データサーバー
‣ 解析過程でいかに情報量を失わせないかが重要
‣ しかし様々な要因によって満足な情報を持ったデータ保存が行えない
要因2:集計処理が複雑・時間がかかる
要因1:散在するログの集約に時間がかかる
要因4:データの取得・表示に手間と時間がかかる
工程・時間
情報量
各種ログ
解析データサーバー
要因3:SQLならスキーマの制約やファイル・テーブルが多く複雑になる
最適な解析データサーバーとは?
‣ 解析過程でいかに情報量を失わせないかが重要
‣ しかし様々な要因によって満足な情報を持ったデータ保存が行えない
解析データサーバーとしてのMySQL
[メリット]
• ドラバの充実
• ノウハウが多数蓄積
• 安定動作
[デメリット]
• スキーマ制約
• スケールがそこそこ大変
フロントエンドバックエンド
[メリット]
• ゕプリ側との親和性
• 検索クエリの充実
• JOINが可能
[デメリット]
• 特に無し
解析データサーバーとしてのHadoop・HIVE・Pig
[メリット]
• 大規模分散処理
• 集計時にJOINが可能
• 簡単なスクリプト言語で記述ができる
[デメリット]
• 処理フローの管理
• 詳細な処理がやや面倒(Hive・Pig)
フロントエンドバックエンド
[メリット]
• 特に無し
[デメリット]
• HDFSの信頼性に不安
• データ取得に手間
• データの検索性が悪い
• フゔル管理が面倒
解析データサーバーとしてのCassandra・HBase
フロントエンドバックエンド
[メリット]
• 特に無し
[デメリット]
• 検索クエリが貧弱
• ンデックスはキーのみ
• コマンドランでの手軽な操作ができない(データのゕクセス性)
[メリット]
• スキーマフリー
• 高い Write 性能
• スケーラビリテゖ
• ドラバの充実
[デメリット]
• 特に無し
解析データサーバーとしてのMongoDB
[メリット]
• スキーマフリー
• ドキュメント指向
• ドラバの充実
• Replica Sets
• Auto Sharding
[デメリット]
• HDD・メモリ消費
• 動作が不安定
[メリット]
• コマンドラン操作の充実
• 豊富な検索クエリ
• 完全ンデックスサポート
• REST・Node.js・ORMが充実
[デメリット]
• 特に無し
フロントエンドバックエンド
MongoDB が最適な理由
[メリット]
• スキーマフリー・ドキュメント指向
‣ MONGODB RIAUNLEASHED 2010
• 豊富な検索クエリ
‣ Creating, Updating and Deleting Document in MongoDB
• コマンドラン操作の充実 (JavaScript)
‣ 必要な関数は定義して保存しておける
‣ 必要な時にすぐにデータを取り出し、見せることができる
→ データを見せながら会話ができる
[メリット]
• 完全なンデックスサポート
‣ あらゆる項目でデータの取得が高速(10億レコードでも高速検索)
‣ Indexing and Query Optimizer (Aaron Staple)
• Replica Sets・Auto Sharding
‣ データのバックゕップが容易→解析者の負担が軽減
‣ MongoDB Replica Sets
‣ Kristina Chodorow's Blog ( Part1 Part2 Part3 )
‣ MongoDB Auto-Sharding at Mongo Seattle
MongoDB が最適な理由
[ブログ]:こちらにも詳細を記述しています…
• 第8回データマニング+WEB勉強会@東京で発表してきました。「MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析」
MongoDB が最適な理由
2. ソーシャルゕプリのログ解析
※データの数値は正しい値はないのでご注意下さい
おみせやさん
▶ 会員数累計300万を誇る弊社ソーシャルゕプリのGREE版
▶ ゕクセスログ12GB / 日、行動ログ5GB / 日
▶ MySQL + Cassandra + Scala ( Lift ) による実装
▶ MongoDB + GraphDB によるデータ解析
▶ gumiStudy#6 300万人が遊ぶソーシャルゕプリ「おみせやさん」の作り方 →ンフラ関連のおはなし
過去の発表資料#TokyoWebMining
• HadoopとMongoDBを活用したソーシャルゕプリのログ解析 [2010/09/26]
‣ 関連ブログ
‣ ※解析バックエンドの話
• MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析[2010/11/14]
‣ 関連ブログ
‣ ※解析フロントエンド + GraphDB ( Neo4j ) の話
2-1.ログ解析バックエンド
Hosting Server
Flash ComposeServer
Cassandra18ノード
MySQL
Webserver(nginx)
7台
Appserver(Tomcat)
27台
ゲームセーブデータ(ユーザーステータ
ス)
アクセスログ
ランキング課金情報登録日
行動ログ
ゕクセスの流れ
主に4種類のデータが解析対象
ランキング課金情報登録日
解析バックエンド
行動ログアクセスロ
グ
データセンター(ホステゖング
ゲームセーブ
データ
MySQLCassandra
Dumbo (Python + Hadoop )整形・フゖ
ルタリング
全集計結果はMongoDBに格納
Python Script
整形・集計データ
scribe でローカルのHDFS上に格納
Thrift & PHP(API)
解析フロントエンド
Sharding×3Replica Set×3
Server× 3
前処理としてのHadoop
• データの整形
‣ MongoDB に格納するためにフォーマットの統一
• データのフゖルタリング
‣ 1日約1億レコードある行動ログの情報削減
→ 解析を進めていく上で判明した不要項目は読み飛ばし1日1000万レコード程度に削減
• 簡単な集計
• 今後のデータ増大に備えて
‣ サービスが増えてもスケールゕウトできるように
Dumbo
• [説明]
‣ Python + Hadoop = Flying Circus Elephant
‣ Last.fm で使用
‣ Hadoop Streaming を実行
‣ map/reduce の記述が楽
‣ 簡単な join もできる
‣ デバッグが容易
http://github.com/klbostee/dumbo
• [例] Dumbo で Word Count
行動ログ集計:Dumbo
def mapper(key, value):
for word in value.split(): yield word,1
def reducer(key, values):
yield key,sum(values)
if __name__ == "__main__":
import dumbo
dumbo.run(mapper, reducer)
dumbo start wordcount.py ¥
-hadoop /path/to/hadoop ¥
-input wc_input.txt -output wc_output
「wordcount.py」
Dumbo
• [メリット]
‣ MapperとReducer、Combinerも1フゔルに記述可
‣ Hadoop Streaming のオプションを引継ぐ
‣ HDFS上のフゔルの操作も可能(fs -ls や –put 等)
‣ Hadoop オプションを指定しない場合は、以下のパプラン処理となり、デバッグ容易
python wordcount.py map < wc_input.txt | sort | ¥
python wordcount.py red > wc_output.txt
Hadoop 処理1.Map:
‣ レコード内の必要な項目のみを抜き出す
‣ 不要なレコードはフゖルタリング
‣ 集計対象となる部分の整形処理(頻度・変化量・対象・複合)
2010-07-26 00:00:02,446 INFO catalina-exec-483 ActionLogger – userId a{Make} make
item onsenmanjyuu
2010-07-26 00:00:02,478 INFO catalina-exec-411 ActionLogger – userId a{LifeCycle}
Login
userId をkeyに、行動詳細部分をJson整形オリジナルンプット
マップからの出力
userId 2010-07-26 00:00:02,446 a{Make} {onsenmanjyuu:1}
userId 2010-07-26 00:00:02,478 a{LifeCycle} {Login:1}
userId 2010-07-26 00:00:02,478 a{GetMaterial} {omotyanomotoPRO:5}
userId 2010-07-26 00:00:02,446 a{putOn} {item:A,user:B}
行動ログ集計
2.Reduce:
‣ [簡易集計] 同じ行動タプはユーザー毎に集計
‣ [デバッグ] 異常値(システムエラー・不正行動)の判定もここで行う
‣ 非数値は頻度集計・数値は合計
‣ 複合要素はそれに応じた集計
‣ [Output] 最終的な出力はMongoDB
‣ HDFS上にはセッションログが書き出される
MongoDB Collection
デリー集計
user_charge
課金情報登録日
行動ログ
アクセスログ
ユーザーステータス
user_trace
user_savedata
user_access
ユーザー毎・日付毎
daily_charge
daily_trace
daily_savedata
daily_access
MongoDB Collection
デリー集計
user_charge
課金情報登録日
行動ログ
アクセスログ
ユーザーステータス
user_trace
user_savedata
user_access
ユーザー毎・日付毎
daily_charge
daily_trace
daily_savedata
daily_access
• [例] ユーザー×日付×タプ:user_trace
行動データ
> db.user_trace.find({date:"2010-11-
10”,actionType:"a{Make}",userId:”7777"}).forEach(printjson)
{
"_id" : "2010-11-10+7777+a{Make}",
"date" : "2010-11-10"
"lastUpdate" : "2010-11-11",
"userId" : ”7777",
"actionType" : "a{Make}",
"actionDetail" : {
"make item ksutera" : 3,
"make item makaron" : 1,
"make item huwahuwamimiate" : 1,
"make item ringoame" : 3,
…
}
}
ユーザー・日付・行動タプごと
行動タプによっては配列や入れ子
の辞書が入る
• [例] 全ユーザー×日付×タプ:daily_trace
行動データ
> db.daily_trace.find({date:{$gte:"2010-11-10”,$lte:”2010-11-20”},actionType:"a{Make}"}).forEach(printjson)
{
"_id" : "2010-11-10+group+a{Make}",
"date" : "2010-11-10",
"lastUpdate" : "2010-11-12",
"actionType" : "a{Make}",
"actionDetail" : {
"make item kinnokarakuridokei" : 615,
"make item banjo-" : 377,
"make item itigoke-ki" : 135904,
"make item wadaiko" : 40,
"make item ha-pu" : 11,
"make item ribontore-sunohigasa" : 13621
...
},
...
}…
11-10から11-20までの範囲指定
• [例] ユーザー×日付×行動タプ:user_charge
課金データ
// 11/10に最も課金してくれたユーザーTOP10
> db.user_charge.find({date:"2010-11-10"}).sort({totalCharge:-1}).limit(10)
.forEach(printjson)
{
"_id" : "2010-11-10+7777+Charge",
"date" : "2010-11-10",
"lastUpdate" : "2010-11-10",
"totalCharge" : 10000,
"userId" : ”7777",
"actionType" : "Charge",
"boughtItem" : {
"アクセサリーの素EX" : 13,
"コネルギー+6000" : 3,
"アクセサリーの素PRO" : 20
}
}
{…
ユーザーごとに内訳が変わってくる
• [例] 全ユーザー×日付×タプ:daily_charge
課金データ
> db.daily_charge.find({date:"2010-11-10",T:"all"}).limit(10).forEach(printjson)
{
"_id" : "2010-11-10+group+Charge+all+all",
"date" : "2010-11-10",
"total" : 100000,
"UU" : 2000,
"group" : {
"わくわくポント" : 1000000,
"アクセサリー" : 1000000,
...
},
"boughtItemNum" : {
"料理の素EX" : 8,
"アクセサリーの素" : 730,
...
},
"boughtItem" : {
"料理の素EX" : 10000,
"アクセサリーの素" : 100000,
...
}
}
ゕテムのカテゴリ別の内訳
MongoDB Collection
user_registration
課金情報登録日
行動ログ
アクセスログ
ユーザーステータス
user_category
user_error
ユーザーの登録日・最終ログン日・総課金額・初課金日 etc…
属性で分類したカテゴリごとの内訳(人数・
課金額)etc…
異常値:ex. システムエラー・欠損値・不正行
動 etc…
ユーザー属性抽出
MongoDB Collection
user_registration
課金情報登録日
行動ログ
アクセスログ
ユーザーステータス
user_category
ユーザー属性抽出
user_error
ユーザーの登録日・最終ログン日・総課金額・初課金日 etc…
属性で分類したカテゴリごとの内訳(人数・
課金額)etc…
異常値:ex. システムエラー・欠損値・不正行
動 etc…
• [例] ユーザー毎の属性データ:user_registration
ユーザー属性データ
> db.user_registration.find({userId:”7777"}).forEach(printjson)
{
"_id" : "2010-06-29+7777+Registration",
"userId" : ”7777"
"actionType" : "Registration",
"category" : {
“R1” : “True”, #直近1週間ログンしていない場合 = True
“T” : “ll” #プレ期間が長期のユーザー
…
},
“firstCharge” : “2010-07-07”, #初課金日
“lastLogin” : “2010-09-30”, #最終ログン日
“playTerm” : 94, #プレ期間
“totalCumlativeCharge” : 50000, #総合課金額
“totalMonthCharge” : 10000, #直近1ヶ月の課金額
…
}
課金額・期間・登録日等に応じてカ
テゴラズ
• [例] 属性毎の内訳を計算:user_category
属性カテゴリデータ
> var cross = new Cross() //ユーザー定義関数
//月額課金×プレ期間(退会ユーザー)
> MCResign = cross.calc(“2010-10-08”,“MC”,1)
課金/期間 0円(z) ~1000円(s) ~10000円(m) 10000円~(l) 合計
~1日(z) 50000 10 5 0 50015
~1週間(s) 50000 100 50 3 50153
~1ヶ月(m) 100000 200 100 1 100301
~3ヶ月(l) 100000 300 50 6 100356
3ヶ月~(ll) 0 0 0 0 0
//月額課金×プレ期間(現役ユーザー)
> MCNotResign = cross.calc("2010-10-08","MC",-1)
課金/期間 0円(z) ~1000円(s) ~10000円(m) 10000円~(l) 合計
~1日(z) 50000 10 5 0 50015
~1週間(s) 50000 100 50 3 50153
~1ヶ月(m) 100000 200 100 1 100301
~3ヶ月(l) 100000 300 50 6 100356
3ヶ月~(ll) 0 0 0 0 0
…
user_registraton.catagory のタグごとに集計する関数
//ユーザー定義関数
> access = getAccessData(“tutorial”,“2010-12-01”)
UU PATH
10000 /playshop2-gree/tutorial/FirstTopPage
9500 /playshop2-gree/tutorial/Tutorial01Page
8000 /playshop2-gree/tutorial/Tutorial02Page
7700 /playshop2-gree/tutorial/Tutorial03Page
7000 /playshop2-gree/tutorial/Tutorial04Page
4000 /playshop2-gree/tutorial/make/avatar
3800 /playshop2-gree/tutorial/Tutorial05Page
…
• [例] チュートリゕルページの離脱状況を確認:daily_access
ゕクセスデータ
daily_access から“tutorial”を含むゕドレスの値でソー
トして表示
01Page、04Pageに問題
データを格納する時のポント
• [形式]
‣ どのコレクションも1レコードあたり「ユーザー×日付×行動タプ」で統一
‣ デリー集計の場合は userId = “group”
‣ _idも”{userId}+{date}+{actionType}”で統一して記述
• [メリット]
‣ ユーザー・日付・行動タプの3軸で集計できる
‣ 検索時、collection間で統一したクエリーで記述できる
‣ _idの明確なルール化で容易にレコード特定
2-2.ログ解析フロントエンド
解析フロントエンド
Sleepy.Mongoose
解析対象データ
GraphDB
WebUI
解析ツール
ソーシャルデータゕクセスログ(遷移データ)
WebUI
• [目的]
‣ 社員全員で共有できるようにWebでデータを公開
‣ 基本はデリーの課金・行動データを出力
‣ 社内ツールなので無駄な作り込みは不要
‣ 取得している全てのデータにゕクセス可能
‣ 要望に応じて柔軟に項目追加できる仕様
WebUI:検討した仕様
• ① MVC + MongoDB → Ming
• ② node.js + MongoDB → Mongoose
• ③ REST Interface + MongoDB →
sleepy.mongoose
WebUI:検討した仕様 ①
• ①:[MVC + Mongo]
‣ Djangoで実装
‣ スキーマを(ある程度)定義。Validation機能便利。
MongoDBとDjangoをシームレスに扱えるツールが充実:
‣ Python:pymongo
‣ Django :MongoEngine、Ming、MongoKit、Django-nonrel
‣ 参考になるページ
‣ Django and NoSQL, any ready-to-use library?
‣ Which Python API should be used with Mongo DB and Django
‣ MongoDB hearts Django? (Django NYC)
• [例] スキーマの使用例
MVC+MongoDB
from ming.datastore import DataStore
from ming import Session
from ming import Document, Field, schema
bind = DataStore('mongo://localhost:30000/playshop')
session = Session(bind)
class UserTrace(Document):
class __mongometa__:
session = session
name = ‟user_trace‟
_id = Field(str) #標準のBSONオブジェクトなら Field(schema.ObjectId)
userId = Field(str)
actionType = Field(str)
…
#trace.py として保存
db
collection
• [例] スキーマの使用例
MVC+MongoDB
import trace
…
#Ming provides a standard attribute .m, short for “manager”
>>> trace.userTrace.m.find().first()
{ "_id" : "2010-11-10+38733015+a{Make}",
"date" : "2010-11-10"
"lastUpdate" : "2010-11-11",
"userId" : ”7777",
"actionType" : "a{Make}",
"actionDetail" : { "make item ksutera" : 3,…}
}
WebUI:検討した仕様 ②
• ②:[node.js + Mongo]
‣ サーバサド Java Script
‣ クラゕントのリクエストをサーバー側で実行して結果を返す
‣ Mongoose は数種ある中で代表的なサーバサドJSラブラリ。
‣ Node.js 内で動くJava Script Library
‣ 未実装部分もあるが、十分使える
‣ Hummingbird がMongoDB+node.jsを使用した実例
‣ 参考になるページ
‣ Node.js and MongoDB
‣ node.js + express + mongodb + mongoose を試してみた
‣ Real time ecommerce analytics with MongoDB at Gilt Groupe
• [例] もっとも簡単な例
node.js+MongoDB
var mongoose = require('mongoose/').Mongoose,
db = mongoose.connect('mongodb://localhost/playshop'),
Collection = mongoose.noSchema(‟user_trace',db);
Collection.find({„date‟:‟2010-11-10‟}).each(function(doc){
// do something
});
• [例] Modelを利用した例
node.js+MongoDB
var mongoose = require('mongoose/').Mongoose,
db = mongoose.connect('mongodb://localhost/playshop');
mongoose.load('./models/');
User = mongoose.get(‟UserRegistration',db);
var user = new User({userId :‟7777', totalCharge : 10000, …});
user.lastLogin = „2010-11-10‟; // change a key value
user.save()
User.find({„date‟:‟2010-11-10‟}).each(function(user){
// do something…
});
• [参考書籍]
• 7章に「MongoDB mit Node.js」
node.js+MongoDB
•MongoDB Sag ja zu NoSQL
•Marc Boeker
•Dezember 2010
•220 Seiten, Softcover
•ISBN: 978-3-86802-057-1
•E-Book-ISBN: 978-3-86802-244-5
•Preis: 24,90 € / 25,60 € (A)
•eBook Preis: 16,00 €
WebUI:検討した仕様 ③
• ③:[REST Interface + Mongo]
‣ HTTP GET/POSTリクエストでデータを受け取る
‣ sleepy.mongoose
‣ /db_name/collection_name/_command 形式でリクエスト
‣ 10genのエンジニゕ @kchodorow さんが作った純正ツール
‣ Pymongo、pyOpenSSL を内部的に使用
‣ 参考になるページ
‣ Sleepy.Mongoose: A MongoDB REST Interface
• [例] 使用例
REST Interface + Mongo
//server起動
> python httpd.py
…listening for connections on http://localhost:27080
//MongoDBに接続
> curl --data server=localhost:30000 'http://localhost:27080/_connect‟
//クエリー の例
> curl -X GET 'http://localhost:27080/playshop/daily_charge/_find'
> http://localhost:27080/playshop/daily_charge/_find?criteria={}&limit=10&batch_size=10
{"ok": 1, "results": [{“_id": “…”, ”date":… },{“_id”:…}], "id": 0}}
• [例] 使用例
REST Interface + Mongo
//細かい条件でリクエストが可能
>http://localhost:27080//playshop/daily_charge/_find?criteria={“date”:{$gte:”2010-11-
01”,”$lte”:”2010-11-13”}}&sort={“date”:1}&limit=100&batch_size=100
{"ok": 1, "results": [{"date": "2010-11-01", "_id": "2010-11-01+group+Charge+all+all", "group":
…},{…},…,”id”:1}
フロントはsleepy.mongoose
• [結論] sleepy.mongoose を採用
‣ 最も手軽(基本実装1日で完了)
‣ Ajaxと併せて非同期通信
‣ 今回必要な検索条件は全て使用できる事を確認
‣ 1回のデータ量もそれほど大きくない
‣ MongoDBとHTMLを仲介するフゔルが不要
WebUI:テーブル・グラフ
• [テーブル]
‣ 日毎の集計値を表で出力したい
‣ 各項目でソートしたい
‣ できるだけ簡単に実装したい
‣ jQuery.DataTables
‣ 項目ごとのソート機能
‣ 表示数指定・ページネーション機能
‣ 検索機能
‣ 精錬されたデザン
‣ $(document).ready(function(){ $(’#tableArea').dataTable();});
WebUI:テーブル・グラフ
• [グラフ]
‣ データの可視化
‣ 主に時系列チャート
‣ できるだけ簡単に実装したい
‣ jQuery.HighCharts
‣ 多数のグラフが用意されている
‣ 精錬されたデザン
‣ ンタラクテゖブなグラフも可能
‣ ドキュメントが充実
WebUI:まとめ
• データ取得・描画がJSON形式でほぼダレクトにやりとり
• 非常に手軽かつ高性能
JSONSleepy.Mongoose
jQuery
WebUI:実例
‣ デリーの全ての課金内訳、行動内訳が閲覧可能
‣ CSVダウンロードリンク
‣ 特定のユーザーの課金、行動履歴を全てトラッキング可能
‣ 属性ごとのユーザー数内訳、分布
WebUI:実例
WebUI:実例
WebUI:実例
2-3.まとめ
• [まとめ]
‣ 3ゲーム・計500GB・10億レコードでも余裕
‣ スキーマレスかつ検索クエリが豊富なのが強い
‣ 自前スクリプトも定義でき、コンソールから様々な操作ができる
‣ データの増加に対しても容易にスケールできる
‣ 解析目的では、コレクション数やンデックス対象になる項目がそれほど多くない
ログ解析 + MongoDB:ベストプラクテゖス
3. MongoDB その他のトレンド
3-1. Log to MongoDB
Log to MongoDB
• Logging Application Behavior to MongoDB
‣ ゕプリケーションのログを中央管理できる
‣ フゔルの場合と比べてリモートでゕクセスしやすい
‣ ドキュメント指向と相性がよい。(フゔルログの各項目をキーに、値をバリューにできる)
‣ スキーマレスなので様々なログ形式に対応
‣ ンデックスと豊富なクエリーを活用
‣ Capped collection がこの用途において非常に効果的
‣ JavaScript MapReduce によってデータ集約が可能
Log to MongoDB
• [Capped Collection]
‣ 固定サズのコレクション(古いデータから削除される)
‣ insert処理に特化、非常に高パフォーマンス(update処理不可)
‣ ンデックス無・検索結果はinsert順(log tailing)
• [JavaScript Map Reduce※]
‣ MongoDB の Map Reduce、JavaScript で記述
‣ Sharding 間でスケールが可能
※現在1つのmongodプロセスでのMapReduce処理はシングルスレッドの制約がある
ランキング課金情報登録日
解析バックエンド(今)
行動ログアクセスロ
グ
データセンター(ホステゖング)
ゲームセーブ
データ
MySQLCassandra
Dumbo (Python + Hadoop )整形・フゖ
ルタリング
全集計結果はMongoDBに格納
Python Script
整形・集計データ
scribe でローカルのHDFS上に格納
Thrift & PHP(API)
解析フロントエンド
Sharding×3Replica Set×3
Server× 3
ランキング課金情報登録日
解析バックエンド(案)
MySQL
Python Script
行動ログ
アクセスログ
ゲームセーブ
データ
user_trace
user_savedata
user_access
capped collection
capped collection
capped collection
JavaScript MapReduce
Update/hour
Update/hour
Update/hour
Modifier Operations
RealTime
RealTime
RealTime
3-2. MongoDB + Hadoop
MongoDB + Hadoop
The Elephant In the Room: MongoDB + Hadoop [pdf]
MongoDB + Hadoop
• [Hadoop]
‣ github: mongo-hadoop
‣ 現在は Java ドラバのみ
‣ Hadoop の入力として MongoDB のコレクションを指定できる
‣ Hadoop の出力先にも MongoDB のコレクションを指定できる
‣ MongoDB 独自のJavaScript MapReduce より柔軟で強力な大規模分散処理が可能になる
MongoDB + Hadoop• [Pig]
‣ 現在は MongoDB を出力先でのみ指定可能
‣ 将来的には入力先でも指定可能になる予定
-- Use the PigStorage function to store the results.
--Output:(hour, n-gram, score, count, average_counts_among_all_hours)
> STORE ordered_uniq_frequency ¥
INTO ’mongodb://localhost/test.pig.output‟ ¥
USING com.mongodb.hadoop.pig.MongoStorage;
> db.pig.output.find()
{
"_id" : ObjectId("4cbbbd9487e836b7e0dc1052"),
"hour" : "07”, "ngram" : "new”,"score" :2.4494897427831788,
"count" : NumberLong(2), "mean" : 1.1428571428571426
}
Flume User Guide(changed)
MongoDB + Hadoop• [Flume]
‣ Sink (出力先)に MongoDBを指定可能
‣ github: mongo-fadoop/flume_plugin
MongoDB
3-3. グラフ構造データ解析
グラフ構造データ解析
• [グラフ構造を持ったデータ]
‣ ノードとエッジとその属性値で表現できるような構造を持ったデータ
‣ ソーシャルデータ:TwitterのFollow関係、mixiのマミク関係
‣ ゕクセスログ:ページ間の遷移データ・コンバージョン
‣ リコメンドエンジンで使用するデータ
‣ その他多くのデータが実はグラフ構造で表現可能
グラフ構造データ解析• [特殊な検索方法]
Building a Social Network with MongoDB[pdf]
グラフ構造データ解析
• [特殊な検索方法]
‣ 近傍検索(友達の友達を探索)
‣ 重み付け検索(エッジの属性値で重み付け)
‣ こういった検索を GraphDB 以外でやるのは面倒
> SELECT ?person WHERE {
?person KNOWS ?friend
?friend KNOWS ?classmate
?classname name “Takahiro Inoue”
}
MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析 (from 55 page)
グラフ構造データ解析
• [MongoDB でグラフ構造を扱う]
‣ Building a Social Network with MongoDB
‣ MongoDB でソーシャルデータの解析方法を述べたチャレンジングな資料
‣ 近傍のデータを配列に格納、$in で検索可能に
‣ 工夫次第でグラフデータの解析も
‣ しかし、パフォーマンスは不明、かつレコードの保存形式が複雑になる場合も
4. 最後に
今後の活動
• [解析者の存在価値を高めて行きたい]
‣ 到来する”BigData”の時代において、解析者が非常に重要な存在になっていく事を証明していきたい
‣ それは自分の居場所をかけた戦いでもあり…
‣ 解析バックエンドを担える人は非常に重要。そしてその強力な武器となるのがHadoopやNoSQL
‣ MongoDBと出会いで色んな可能性が見えてきた
‣ なのでMongoDBやデータ解析の話をさせてくれる機会があればいつでも声をかけて下さい
ありがとうございました
‣ 10gen
‣ MongoDB Documentation
‣ mongodb-user
‣ MongoDB JP
‣ CouchDB JP
‣ nosql-ja