32
MongoDB紹介 2012/5/18 matsumura

Mongodb 紹介

Embed Size (px)

Citation preview

Page 1: Mongodb 紹介

MongoDB紹介

2012/5/18 matsumura

Page 2: Mongodb 紹介

MongoDBってなんぞ - 多機能 but 発展途上 •  ドキュメント指向データベース

o  最新2.0.5 •  自動シャーディング

o  Read / Writeがスケールアウト

•  自動フェイルオーバー o  Master deadでも自動でフェイルオーバー

•  柔軟なクエリ o  SQLで可能なことはJOIN句以外 一通りできる

•  スキーマレス o  データによって自由に持つものを決められる

他にも多機能

Page 3: Mongodb 紹介

構成例

Web mongos

Web mongos

Mongod (config)

Mongod (config)

Mongod (config)

meta

Replica set

mongod

mongod

mongod

Replica set

mongod

mongod

mongod

data data

3processで最適化 最小構成台数

3process

Page 4: Mongodb 紹介

基本的なデータの持ち方

mongod

データベース etcr

データベース other

コレクション 行動履歴 コレクション XXマスタ

コレクション 各種ログ

doc doc doc

doc doc doc

doc doc doc

doc

doc doc doc

mysqld

MySQLで例えると

データベース

テーブル

レコード

Page 5: Mongodb 紹介

レプリカセット - MySQL同様

Mongod (Primary)

データベース etcr

コレクション 行動履歴

docA docB docC

docD docE docF

データベース local

コレクション oplog

操作 操作 操作

Mongod(Secondary)

データベース etcr

コレクション 行動履歴

docA docB docC

docD docE docF

データベース local

コレクション oplog

操作 操作 操作

Mongod(Secondary)

データベース etcr

コレクション 行動履歴

docA docB docC

docD docE docF

データベース local

コレクション oplog

操作 操作 操作 同期

再現 再現

Page 6: Mongodb 紹介

自動フェイルオーバー •  Primaryが死ぬ

•  Primaryが死んだことがreplica set内で共有 •  残ったノードで投票を行う •  ノードごとの優先度設定、最終同期時刻をもとに投票を行う

•  過半数より多くの票を集めたノードがPrimaryとなる

•  この間 約20s ~ 60s

Page 7: Mongodb 紹介

Mongod (Shard A)

自動シャーディング - phase1

データベース etcr

コレクション 行動履歴

Mongod (Shard B) データベース etcr

コレクション 行動履歴

Chunk ( –無限大 〜 無限大]

docA docB docC

デフォルト 200MB

Page 8: Mongodb 紹介

Mongod (Shard A)

自動シャーディング - phase2

データベース etcr

コレクション 行動履歴

Mongod (Shard B) データベース etcr

コレクション 行動履歴

Chunk ( –無限大 〜 D]

docA docB docC

Chunk ( D 〜 無限大]

docD docE docF

Page 9: Mongodb 紹介

Mongod (Shard A)

自動シャーディング - phase3

データベース etcr

コレクション 行動履歴

Mongod (Shard B) データベース etcr

コレクション 行動履歴

Chunk ( –無限大 〜 D] docA docB docC

Chunk ( D 〜 無限大]

docD docE docF

docC’ docC’’ docC’’’

Page 10: Mongodb 紹介

Mongod (Shard A)

Chunk (C’ 〜 D]

自動シャーディング - phase4

データベース etcr

コレクション 行動履歴

Mongod (Shard B) データベース etcr

コレクション 行動履歴

Chunk ( –無限大 〜 C’]

docA docB docC

Chunk ( D 〜 無限大]

docD docE docF

docC’ docC’’ docC’’’

Page 11: Mongodb 紹介

Mongod (Shard A)

Chunk (C’ 〜 D]

自動シャーディング - phase5

データベース etcr

コレクション 行動履歴

Mongod (Shard B) データベース etcr

コレクション 行動履歴

Chunk ( –無限大 〜 C’]

docA docB docC

Chunk ( D 〜 無限大]

docD docE docF

docC’ docC’’ docC’’’ 水平方向に スケールアウト

Page 12: Mongodb 紹介

自動シャーディング - phase6

• Sharding Demo

Page 13: Mongodb 紹介

スキーマレス

• Create table, Create column family 不要 o  Insertした時点で作られる o アプリ要件に合わせて柔軟に入れられる Item1 = {

_id: ObjectId('4b0552b0f0da7d1eb6f12xxx'), name: 秘薬, price: 100,

} Item2 = {

_id: ObjectId('4b0552b0f0da7d1eb6f12yyy'), name: 自分用秘薬,

}

Page 14: Mongodb 紹介

柔軟なクエリ

• SQL文を持たない • Demo • ハッシュでO/Rマッパーのように指定する

o フロントjavascriptからクエリオブジェクトを送って、サーバーサイドでは検証後、即実行できる

Page 15: Mongodb 紹介

クエリ 周辺の話 (1)

• Index(B-Tree) o 配列やオブジェクトに対してもはれる

§ ただし、配列は1つ / indexに制限 o メモリに乗るようにintを使うと吉

// indexをつける db.test.ensureIndex({x:1, y:1, z:1}) ○ db.test.find({x:'a'}) ○ db.test.find({x:'a', y:'b'}) ○ db.test.find({x:'a', y:'b'}).sort({z:1}) // 順序が重要 × db.test.find({y:'b', x:'a'})

Page 16: Mongodb 紹介

クエリ 周辺の話(2)

• クエリオプティマイザ o MySQLのようなコストベースではない o 初回のクエリで複数クエリプランを同時実行 o 最も早かったクエリを利用 o データ量に応じて定期的に見直し o explain()

Page 17: Mongodb 紹介

クエリ 周辺の話(3)

• Capped コレクション o あらかじめサイズを決めたコレクション o 古いものから順次消えていく o 挿入順での検索で高速 o Shardingできない o 削除不能 o Create文を明示的に発行して作成

§ db.createCollection("mycoll", {capped:true, size:100000})

Page 18: Mongodb 紹介

クエリ findの話 (1) • 検索条件は、bsonオブジェクトの先頭に寄せる

{ owner_id: 123, request: { type: '合成', params: {}}, process: {category: 'composit'}, memo: ['lv.0 -> lv.15'], concerned: [ {io: 'i', type: 'card', id: 100, object: '111', base: true}, {io: 'i', type: 'card', id: 201, object: '222'}, {io: 'o', type: 'card', id: 100, object: '111'}, ] })

1. db.activityHistoryDemo.find({owner_id: 123})

2. db.activityHistoryDemo.find({‘concerned.id’: ‘201’})

Page 19: Mongodb 紹介

クエリ findの話 (2) •  bsonオブジェクト階層を細分化したほうが早い

{ owner_id: 123, request: { type: '合成', params: {}}, process: {category: 'composit'}, memo: ['lv.0 -> lv.15'], concerned: [ {io: 'i', type: 'card', id: 100, object: '111', base: true}, {io: 'i', type: 'card', id: 201, object: '222'}, {io: 'o', type: 'card', id: 100, object: '111'}, ] })

db.activityHistoryDemo.find({‘concerned.id’: ‘201’})

Page 20: Mongodb 紹介

クエリ findの話 (3) • 条件の指定順序

o  And条件は結果の小さな条件から順次 §  補集合を無視するので。

o  Or条件は結果の大きな条件から順次 §  後続条件は補集合から検索するので。

○ db.sample.find({owner_id: 123, ‘concerned.type’: ‘card’})

× db.sample.find({‘concerned.type’: ‘card’, owner_id: 123})

○ db.sample.find({$or: [{‘concerned.type’: ‘card’}, {owner_id: 123}])

× db.sample.find({$or: [{owner_id: 123}, {‘concerned.type’: ‘card’}])

Page 21: Mongodb 紹介

クエリ findの話 (4) •  DBRef

doc = { name: 'ryooo', card:[ {'$ref': 'card', '$id' : ObjectId('4b0552b0f0da7d1eb6f12xxx')}, ] } doc.card[0].fetch() // ←カードオブジェクトがとれる

@ruby db = Connection.new.db(”etcr ") user_card = db["user_card"].save({:name => ”ryooo”, :card_id => 123}) ref = DBRef.new(”card", user_card.card_id) db.dereference(ref) #=> カードオブジェクト

Page 22: Mongodb 紹介

クエリ findの話 (5) • 検索条件に関数も使える(javascript)

• mongoサーバーサイドに関数を登録できる

// 極端な話、こんなクエリも書けちゃいます db.cards.find(function(){ row = db.user_summary.findOne({owner_id: this.owner_id}) return this._id == row.leader_card_id; })

// 関数を登録 db.system.js.save({_id:’name', value: function (){ //implementation }}); f = db.system.js.findOne({_id:’name'}) // 検索で利用(fはサーバー側で実行される) Db.cards.find(f)

Page 23: Mongodb 紹介

Mongod (Shard A)

クエリ findの話 (6)

データベース etcr

コレクション 行動履歴

Mongod (Shard B)

データベース etcr

コレクション 行動履歴

Chunk

docA docB docC

Chunk

docD docE docF

Shard keyを利用したクエリ Shard keyを利用しないクエリ

targeted global

Page 24: Mongodb 紹介

クエリ insert/updateの話 (1) •  fire and forget

o  発火即忘却 §  結果を確認せずreturnする §  結果を知りたければgetlasterrorオプションを指定

• 確実にcommitさせる o  データファイルにフラッシュさせる

§  fsync: true o  2台のメンバーに書き込みが完了するまで待機(timeout:5000)

§  db.getlasterror(2, 5000) §  db.getlasterror('majority')

Page 25: Mongodb 紹介

クエリ insert/updateの話 (2) •  ID値

o  デフォルトでは、IDは自動で振られる o  ObjectId = BSON(

[4byte timestamp] + [3byte hash(hostname)] + [2byte pid] + [3byte inc])

// parseすれば時間やサーバーなどもわかる object_id = '4b0552b0f0da7d1eb6f12yyy’ createdDt = new Date(parseInt(object_id.substr(0, 8), 16) * 1000) #=> Thu Nov 19 2009 23:14:08 GMT+0900 (JST)

Page 26: Mongodb 紹介

クエリ insert/updateの話 (3) •  Padding

o  insert時に、パディング領域を確保している §  配列に追加されるなど、ドキュメントサイズが拡大しても高速にupdateするため(In-place update)

o  Padding領域を越える更新 §  ドキュメントの再配置が発生(遅い) §  増加性を持ったコレクションはPaddingサイズ調整が必要

•  Atomicな操作 o  1つのドキュメントの更新に対して別のクエリをブロック o  トランザクションのACIDのA(atomic : all or nothing)ではない。 o  sharding環境でサポートされない

Page 27: Mongodb 紹介

クエリ removeの話 • 断片化

o  削除時はドキュメントの再配置を行わないので断片化する

o  repairコマンド §  同容量の空き領域が必要 §  サーバー単位(sharding環境なら各shardで)

o  compactコマンド §  より少ない空き領域で可能 §  コレクション単位 §  paddingも削除するので、増加性を持ったコレクションはデフラグ後にupdateパフォーマンス悪化

Page 28: Mongodb 紹介

困った話 - 1 •  flush前のデータロスト

o  デフォルトでは60sに1回flushされるまではメモリで保持 §  最大で60秒間のデータロストの可能性

o  対策1 (~ver1.8) §  60秒の設定を短縮する §  getlasterror()でflushさせる

•  重くなる o  対策2 ジャーナルモード (ver1.8~)

§  ジャーナルログ(disc)に100msに1回書き込む §  flushと違い、データの更新先などを意識しないため早い §  起動時にJournalディレクトリがあれば復元し、正常終了時はディレクトリを削除する。

Page 29: Mongodb 紹介

困った話 - 2 • 書き込み時(flush時)はDBロックする

o  あまり問題にならないほど、書き込みは高速とのこと §  ほんまかいな

• 非効率なCPUリソース利用 o  書き込み処理とMapReduceではシングルコアしか使えない o  読み込みは複数コアを使う

Page 30: Mongodb 紹介

みんなが苦労しているのは •  Shard key の決め方

o  Chunkの移動があまり起こらないこと o  長期の運用でも綺麗に分散すること o  Shard keyを使って効率よく検索できること

•  Shard keyは一度決めると変えられない

• Migration中の残念なパフォーマンスと不整合

Page 31: Mongodb 紹介

Shard keyの考察 (うけうり) •  [bad] 離散データ

o  chunk分割できない §  例:都道府県コード

•  [bad] 単純インクリメントデータ o  最後のchunkのみが分割移動される

§  例:連番

•  [bad] ランダム値 o  十分に分散するまでは偏りがあるため、大きなchunkができる

§  例:ハッシュ

•  [good] 緩やかに増加するキーと検索に利用するキーの組み合わせ o  検索利用キーでひと月かけて偏りが発生してくるが、ひと月たてば偏りがリセットされる §  例:yyyymm-owner_id

Page 32: Mongodb 紹介

解析用サーバー

シンプルな解析PFの例

Web Web

日次増分をMap/Reduceで集計

認証機能が必要なため。 I/Oをjsonで一致させて

開発スピードアップ

使ったことないものを 仕事で使ってみたいという想い