introduction to mongodb
DESCRIPTION
TRANSCRIPT
Introduction to MongoDB
@just_do_neet
1
Today’s Agenda
•MongoDBの一般的な解説
•向いてそうな適用範囲
•ソーシャルゲームとMongoDB(資料紹介のみ)
•まとめ
今日のお題目
2
MongoDBの一般的な解説
3
MongoDBMongoは「でっかい」という意味らしいです
http://www.mongodb.org/
http://www.mongodb.jp/
•10gen社が主体として開発しているオープンソース所謂「NoSQL」の一つ
4
Features
•ドキュメント指向なデータベース
•スケーラブルなデータベース
よく言われるMongoDBの特徴
5
Document Oriented
•ある一定のフォーマットにてエンコードされたデータをひとつの「ドキュメント」として扱う。
•フォーマット:XML、YAML、BSON、etc.
•ドキュメントは一般的に構造化データの形式を取ることが多い。
• “The central concept of a document-oriented database is the notion of a Document. While each document-oriented database implementation differs on the details of this definition, in general, they all assume documents encapsulate and encode data (or information) in some standard format(s) (or encoding(s)).” http://en.wikipedia.org/wiki/Document-oriented_database
ドキュメント指向の概念
6
Document Oriented
•MongoDBはドキュメントを「BSON」形式で扱う。http://bsonspec.org/
•一つの入れ物(collection)の中には、BSONフォーマットであれば異なる構造のデータでも入れる事ができる。→スキーマレス→柔軟な構造のデータベース
ドキュメント指向の概念
7
Document on MongoDB
> db.musicians.save({name:"Masashi Sada", age:60, genre:"fork"})> db.musicians.save({name:"Spitz", menbers : 4 , companey: "Road & Sky"})> db.musicians.save({name : "Pat Metheny" , country : "US" , awards : { name : "grammy", count:19}})> > db.musicians.find(){ "_id" : ObjectId("4f4ce8621b5c3f27d189c5bc"), "name" : "Masashi Sada", "age" : 60, "genre" : "fork" }{ "_id" : ObjectId("4f4ce8ed1b5c3f27d189c5bd"), "name" : "Spitz", "menbers" : 4, "companey" : "Road & Sky" }{ "_id" : ObjectId("4f4ce95c1b5c3f27d189c5be"), "name" : "Pat Metheny", "country" : "US", "awards" : { "name" : "grammy", "count" : 19 } }
MongoDBの中でのデータ
8
Document on MongoDB
> db.musicians.save({name:"Masashi Sada", age:60, genre:"fork"})> db.musicians.save({name:"Spitz", menbers : 4 , companey: "Road & Sky"})> db.musicians.save({name : "Pat Metheny" , country : "US" , awards : { name : "grammy", count:19}})> > db.musicians.find(){ "_id" : ObjectId("4f4ce8621b5c3f27d189c5bc"), "name" : "Masashi Sada", "age" : 60, "genre" : "fork" }{ "_id" : ObjectId("4f4ce8ed1b5c3f27d189c5bd"), "name" : "Spitz", "menbers" : 4, "companey" : "Road & Sky" }{ "_id" : ObjectId("4f4ce95c1b5c3f27d189c5be"), "name" : "Pat Metheny", "country" : "US", "awards" : { "name" : "grammy", "count" : 19 } }
MongoDBの中でのデータ
各ドキュメントの構造は同じでなくても良い
9
Document on MongoDB
> db.musicians.save({name:"Masashi Sada", age:60, genre:"fork"})> db.musicians.save({name:"Spitz", menbers : 4 , companey: "Road & Sky"})> db.musicians.save({name : "Pat Metheny" , country : "US" , awards : { name : "grammy", count:19}})> > db.musicians.find(){ "_id" : ObjectId("4f4ce8621b5c3f27d189c5bc"), "name" : "Masashi Sada", "age" : 60, "genre" : "fork" }{ "_id" : ObjectId("4f4ce8ed1b5c3f27d189c5bd"), "name" : "Spitz", "menbers" : 4, "companey" : "Road & Sky" }{ "_id" : ObjectId("4f4ce95c1b5c3f27d189c5be"), "name" : "Pat Metheny", "country" : "US", "awards" : { "name" : "grammy", "count" : 19 } }
MongoDBの中でのデータ
ドキュメントの中に階層的なデータを入れることができる。
10
Document on MongoDB
> db.musicians.save({name:"Masashi Sada", age:60, genre:"fork"})> db.musicians.save({name:"Spitz", menbers : 4 , companey: "Road & Sky"})> db.musicians.save({name : "Pat Metheny" , country : "US" , awards : { name : "grammy", count:19}})> > db.musicians.find(){ "_id" : ObjectId("4f4ce8621b5c3f27d189c5bc"), "name" : "Masashi Sada", "age" : 60, "genre" : "fork" }{ "_id" : ObjectId("4f4ce8ed1b5c3f27d189c5bd"), "name" : "Spitz", "menbers" : 4, "companey" : "Road & Sky" }{ "_id" : ObjectId("4f4ce95c1b5c3f27d189c5be"), "name" : "Pat Metheny", "country" : "US", "awards" : { "name" : "grammy", "count" : 19 } }
MongoDBの中でのデータ
各ドキュメントには必ず一意のIDが割り振られる。デフォルトはMongo独自のID(ObjectID)明示的に指定も可。
11
Document on MongoDB
> db.musicians.save({name:"Masashi Sada", age:60, genre:"fork"})> db.musicians.save({name:"Spitz", menbers : 4 , companey: "Road & Sky"})> db.musicians.save({name : "Pat Metheny" , country : "US" , awards : { name : "grammy", count:19}})> > db.musicians.ensureIndex({name : 1})> db.musicians.getIndices()[ {"v" : 1,"key" : {"_id" : 1},"ns" : "music.musicians","name" : "_id_"}, {"v" : 1,"key" : {"name" : 1},"ns" : "music.musicians","name" : "name_1"}]>
MongoDBの中でのデータ
任意のフィールドにインデックスを貼ることができる。(B-Tree)
12
Document on MongoDB
•入れ物の中に、異なる構造のデータを格納することができる(スキーマレス)
•階層構造を持つデータを格納することができる。
•かつ、RDBに近い操作性を持っている。
MongoDBの中でのデータ
13
ScalabilityMongoDBにおけるスケーラビリティ
http://www.mongodb.org/display/DOCS/Introduction
•Replica Set(High Availability)
•Sharding(Horizontal Scaling)
14
•Replica Set(High Availability)
•Sharding(Horizontal Scaling)
ScalabilityMongoDBにおけるスケーラビリティ
http://www.mongodb.org/display/DOCS/Introduction
Replica Setは同一のデータを複数インスタンスで管理することでHA構成を実現するもの。1 Replica Setあたり最低3台が必要。
15
•Replica Set(High Availability)
•Sharding(Horizontal Scaling)
ScalabilityMongoDBにおけるスケーラビリティ
http://www.mongodb.org/display/DOCS/Introduction
Shardingはデータを複数クラスターで分散配置させるための仕組み。(≒マルチマスタ化)
16
Scalability
•標準機能としてReplica Set / Sharding機能が備わっている。
•カタログスペック上は手軽にHA構成、水平sharding構成を組むことができる。
•実際はshard間のデータ偏り調整など運用にコツがいる
MongoDBにおけるスケーラビリティ
17
Other Features
•GridFS
•大きいサイズのファイルを扱うための仕組み
•地理空間インデックス
•緯度経度検索
•Capped Collection
•固定サイズの入れ物。サイズを超えたら古いものから自動的に削除される。
その他の特徴的な機能
18
Cons.
•トランザクション未サポート
•トランザクションは甘え (ドヤァ
•Global Lock(2.2からCollection Lockに?)
•システムリソースが肥大化(メモリ、ディスク)
•データ圧縮未対応(通信、データストア共)
•セキュリティ周りが弱い etc.
MongoDBの欠点(主観含む)
19
Cons.
•厳密なトランザクション処理が必要なシステムには向かない。(課金、会員管理など...)
•書き込み過多なシステムには基本向かない。
•Big Dataを扱う環境には向かない。
•スケールするが故に、下手にそれなりの規模のシステムに導入するとサーバー無限増殖の刑に...
MongoDBの欠点(主観含む)
20
Ref. PFI Tech. White Paper参考:PFI Technical White Paper
http://preferred.jp/wp-content/uploads/2012/03/PFIwhitepaper.pdf
(P.17)
21
Compress vs Not Compress
•下記例は同一フォーマットの文字列データを格納した際の比較(MongoDB / HBase)
•MongoDBはHBase(snappy圧縮時)の三倍強。
圧縮:非圧縮のデータサイズの差
0100000000200000000300000000400000000500000000600000000700000000
size(1,000,000 record)
MongoDBMongoDB(fragment)HBaseHBase(fragment)HBase(snappy)
22
Summary
•ドキュメント指向DB。異なる構造や複雑な構造のデータを扱える。検索機能も強力。
•HA機能、Sharding機能を標準的に持っている。
•トランザクションは甘え。
•富豪的な作りのミドルウェアなので使用するリソースの多さに起因する課題があるので注意。
ここまでのまとめ
23
向いてそうな適用範囲
24
Suitable Cases
•(注)下記以外にも適切な使い方はたくさんあると思うので皆さんも考えてください。
1.RDBやKVSでは表現しきれない複雑な構成のデータを扱う。
2.一時的なログ集計、ログ管理。データ集計基盤。
3.プロトタイピング用の環境。
向いてそうな使い方(主観)
25
#1 Complex Data
•既存のRDBやKVSでは扱いづらいデータ。
•RDBは複数の構造(schema)のデータをひとつの入れ物(table)に入れて扱いづらい
•KVSは自由度が高いが、Valueの検索が難しい。
•複数の構造のデータをひとつの入れ物に入れて、検索性も高めるためにはどうすれば?
複雑な構成のデータ
26
#1 Complex Data
•例:ソーシャルサービスのActivity Feed
複雑な構成のデータ
http://photoalbum.naver.jp/
27
#1 Complex Data
•例:ソーシャルサービスのActivity Feed
複雑な構成のデータ
•Activityごとにデータ構造が違う。(コメント、like 、写真 etc...)
28
#1 Complex Data
•例:ソーシャルサービスのActivity Feed
複雑な構成のデータ
•ひとつのActivityの中に複数のアイテムが存在するケースがある。
29
#1 Complex Data
•例:ソーシャルサービスのActivity Feed
複雑な構成のデータ
•Activityに含まれるアイテム(写真など)を個別に検索する必要がある。(データの消し込みなど)
30
#1 Complex Data
•RDBでモデリングした場合
•Oops...
複雑な構成のデータ
31
#1 Complex Data
•KVSでモデリング?した場合
•Valueの検索に課題
複雑な構成のデータ
32
MongoDB Can Do It!
•そこでMongoDBですよ。
•スキーマレスなので...
•複数のフォーマットのActivityをひとつの入れ物に詰め込める。
•かつ検索性能も落とさずに済む。
MongoDBならできるよ!
33
Delete Photo(Column)例:写真の削除
#lookup photodb.activity.find({feedList.feedData.photoList, photoId})#delete photodb.activity.remove({feedList.feedId, feedId})#re-insert timeline datadb.activity.insert(newFeedData)
34
Delete Album(Row)例:アルバムの削除
#lookup albumdb.activity.find({feedList.feedData.albumList.albumId, alubmId})#delete albumdb.activity.remove({feedList.feedId, feedId})
35
Dot Notationdot notation記法による階層の深いデータの検索
#lookup albumdb.activity.find({feedList.feedData.albumList.albumId, alubmId})#delete albumdb.activity.remove({feedList.feedId, feedId})
•MongoDBはdot notationという記法で階層の深いデータの検索が可能。(db.hoge.find({a.b.c.d.e : 1}) のような形が可)
•インデックスを貼ることも可能。
36
#1 Summary
•複雑な構造のデータを検索性を落とさずに使うにはMongoDBは向いている。
•ただし先に紹介したような設計にするとデータが肥大化しがちなので注意。
•参照・更新のスループットを落とさないためにはデータ・インデックスをオンメモリで乗るサイズに収めるのが前提。
#1 ここまでのまとめ
37
#2 Storing Logs
•ログファイルは多くの場合非構造・スキーマレスで保存されている。
•ただ保存するだけでなく、ログの検索や集計を手軽に行いたい
•RDBなどスキーマを厳密に定義した入れ物はあまり向かない。→MongoDB!
ログファイルの保存先としてのMongoDB
38
Advanced Queries
•MongoDBはNoSQLと言われる群の中では検索・集計クエリーの機能が揃っているのが特徴。
•count()
•group()
•MapReduce
•正規表現
•Aggregation Framework
MongoDBの高度なクエリー
39
Queries : count()
•条件に合致する件数を返す。SQLのcount文とだいたい同じ。
count() 文
> db.accesslogs.find({method : 'GET', code: '200'}).count()6644
40
Queries : group()
•集計処理を実現するための機能。Sharding環境では動かない(後述のMapReduce推奨)
•後述のAggregation Frameworkに今後は統合される。
group() 文
> db.accesslogs.group(... {key: {method: true},... cond: {},... initial: {count: 0}, ... reduce: function(doc, out) { out.count++; }... });[ {"method" : "GET","count" : 6644}, {"method" : "POST","count" : 3}]
41
MapReduce
•Map/Reduceモデルで集計処理を行う。複数のShardで集計した結果をReduceする。
•処理中ずっとLockがかかるのでProductionで実行するには不向き。
MapReuce機能
> db.accesslogs.mapReduce(map ,reduce , {out: { inline : 1}});{ "results" : [ {"_id" : "GET","value" : {"count" : 6644}}, {"_id" : "POST","value" : {"count" : 3}} ], "timeMillis" : 444, "counts" : {"input" : 6647,"emit" : 6647,"output" : 2}, "ok" : 1,}
42
Regular Expressions
•検索条件に正規表現の文を指定できる (PCRE)。ログの検索には便利。
正規表現機能
> db.accesslogs.find({agent : /Mozilla\/5.0/i}){ "_id" : ObjectId("4f2a9ad6a03a3a34ef000001"), "host" : "0.0.0.0""method" : "GET", "path" : "/odai/2132564671424954401", "code" : "200", "size" : "15947", "referer" : "http://matome.naver.jp/", "agent" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7", "time" : ISODate("2012-02-01T02:02:19Z") }{ "_id" : ObjectId("4f2a9ad6a03a3a34ef000002"), "host" : "0.0.0.0","method" : "GET", "path" : "/odai/2132564671424954401", "code" : "200", "size" : "16084", "referer" : "http://matome.naver.jp/", "agent" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7") }
43
Aggregation Framework
•様々な集約ルールをUnixのPipeのような感じでつないでいくことができる機能(2.1.0以降)http://www.mongodb.org/display/DOCS/Aggregation+Framework
Aggregation Framework
http://datablend.be/?p=1400
44
Problem of Log Collecting
•MongoDBにログを保存する際は以下のような点が課題に。
•非構造データ→構造データの変換(生ログ→BSON)
•ログの収集(web/app server→log server)
•ログ保存時の負荷分散(一度にまとめて保存しようとするとMongoDBのGlobal Lockの餌食に...)
ログ収集における課題
45
FluentdFluentd : The event collector service
https://github.com/fluent/fluentdhttp://fluentd.org/doc/http://community.fluentd.org/browse/help-center/
46
FluentdFluentd : The event collector service
•syslogのように、準リアルタイムにネットワーク越しのログ転送が行えるミドルウェア。
•JSON準拠の構造化データでやりとりをする。
•設定・導入が非常に簡単。
•プラグイン形式で入出力処理の拡張が行える
•MongoDBに書き込むためのプラグインもあるhttps://github.com/fluent/fluent-plugin-mongo
47
FluentdFluentd : The event collector service
•以下の構成のようにすると、web/appのログを準リアルタイムで別システム(Hadoop/MongoDB/etc)に書き込む事ができる。
Apps
Apps
Apps
HadoopClusters
mongodfluentd
fluentd
fluentd
fluentd
fluentd
48
FluentdFluentd : The event collector service
•準リアルタイムでログの保存ができると、データの準リアルタイムでの集計や可視化ができる。
49
Fluentd参考資料
http://dl.dropbox.com/u/224433/kamakura_pm_2/index.html
50
#2 Summary
•ログデータの保存集計にMongoDBは向いている
•検索性を落とさずスキーマレスなデータの格納ができる。
•検索・集計クエリーがそれなりに揃っている
•Fluentdと組み合わせると煩わしいログの収集処理も簡単に。欲しいデータが常に手元に。
•一時保存の場合はCapped Collectionが便利
#2 ここまでのまとめ
51
#3 Prototyping
•プロトタイプアプリで「とりあえず動くもの」を作成するにはRDBを使用するのが面倒くさい。
•テーブル作成のたびにcreate table文。
•開発中にDBのスキーマが頻繁に変わる。
•MongoDBなら事前定義不要。クエリー実行した内容のとおりにデータが作成される。
•プログラマ側でコントロールできる。
#3 プロトタイピング向けのDBとしてMongoDBを使用
52
#3 Prototyping参考資料
http://www.slideshare.net/fungoing/mongodb-7948933
53
ソーシャルゲームとMongoDB(資料紹介)
54
Ref. Ameba pico
•『Ameba PicoとMongoDB』http://www.slideshare.net/snamura/mongo-db-couchdb20101214
•『AmebaPico 裏側の技術やAWS活用について』http://www.slideshare.net/KoheiMorino/amebapico-aws
Ameba Pico(piggの海外版)での事例資料
55
Ref. Animal Land
•『ソーシャルゲームにおけるMongoDB適用事例』http://www.slideshare.net/matsukaz/mongodb-animal-land-11134607
Animal Land(海外向けブラウザゲーム)の事例
56
まとめ
57
Conclusion
•広く浅くMongoDBに関する話をしてきました。
•個人的な主観は以下です。
•比較的平和なケース:複雑なデータ構造をメモリに載りきる範囲で運用。ログ集計などバックエンドで使用。
•チャレンジングなケース(お金的な意味で):Big Dataを扱う。大規模システムのストレージとして用いる。
まとめにかえて
58
Conclusion
•開発が活発でたくさんの新機能も予定されているので、今後の進展が期待できるプロダクトです。
•今後の動きにぜひ注目していてください。
•個人的にはRedisも好きです。
•2.6から導入されるLua Scriptingは楽しそうですね
まとめにかえて
59
ご清聴ありがとうございました
60