DB tech showcase: 噂のMongoDBその用途は?
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

DB tech showcase: 噂のMongoDBその用途は?

on

  • 13,007 views

 

Statistics

Views

Total Views
13,007
Views on SlideShare
12,846
Embed Views
161

Actions

Likes
55
Downloads
91
Comments
0

4 Embeds 161

https://twitter.com 150
http://ab-sn5.tumblr.com 8
https://www.chatwork.com 2
http://tweetedtimes.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

DB tech showcase: 噂のMongoDBその用途は? Presentation Transcript

  • 1. 噂のMongoDB その用途は?
  • 2. About me
  • 3. { 名前: 会社: 肩書: 趣味: 悩み: 窪田博昭 Cookpad.Inc   MongoDBJP代表 Golf,フットサル 30代は体が・・・ twitter:@crumbjp github: github.com/crumbjp }
  • 4. We're hiring !!
  • 5. -5 -
  • 6. -6 -
  • 7. -7 -
  • 8. -8 -
  • 9. -9 -
  • 10. -10 -
  • 11. -13 -
  • 12. NoSQL全般  RDBMSから機能を削り  スループットや並列性を確保している  比較的低機能ではあるが一点豪華主義で  部分的にRDBMSを凌駕する機能を持つ  大抵は速度重視
  • 13. -16 -
  • 14. MongoDBの特徴 1. スキーマレス   2. 高機能Index   3. 高速   4. 並列性(& automatic failover)   ・耐障害性   ・スケーラビリティー   5.トランザクション無し    ・代わりのAtomic処理   6.JOIN無し
  • 15. Index -18 -
  • 16. MongoDBのIndex 商品名 ボールペン タグ 値段 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148     食料品で200以下の商品を取得
  • 17. MongoDBのIndex 商品名 タグ 値段 ボールペン 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148 商品・テーブル CREATE TABLE 商品 (   id INT PRIMARY,   商品名 VARCHAR(100) ); タグ・テーブル CREATE TABLE タグ (   商品id INT,   タグ名 VARCHAR(100),   値段 INT,  KEY(タグ名,値段) ); 食料品で200以下の商品 商品投入 ■RDBMS INSERT INTO 商品 VALUES (1,'ボールペン'); INSERT INTO タグ VALUES (1,'日用品',198),    (1,'筆記用具',198);  苦手な処理      : クエリー  ・Index用のテーブルを SELECT * FROM  商品 INNER JOIN タグ   ON タグ.商品id = 商品.id   別途用意しJOIN WHERE タグ名 = '食料品' AND 値段 <= 200;  値段が重複管理で筋が悪い。。
  • 18. MongoDBのIndex 商品名 タグ 値段 ボールペン 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148 商品投入 db.商品.save({  '商品名' : 'ボールペン',  'タグ': ['日用品', '筆記用具'],  '値段':198 } );        :        : 食料品で200以下の商品を取得 インデックス ■MongoDB db.商品.ensureIndex({  'タグ':1, '値段':1 });   データ形式、Index共に クエリー   完全にサポート! db.商品.find({   タグ構造にもってこい!!  'タグ':'食料品',  '値段': { $lte : 200 } });
  • 19. MongoDBのIndex 商品名 ボールペン タグ 値段 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148     食料品で果物の商品を取得
  • 20. MongoDBのIndex 商品名 タグ 値段 ボールペン 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148 食料品で果物の商品 ■RDBMS  SQLでの表現は困難   self join する? クエリー(2タグ限定版) SELECT  * FROM  タグ a  INNER JOIN  タグ b  ON   a.商品id = b.商品id   AND   a.タグ名 != b.タグ名  INNER JOIN 商品 c  ON   a.商品id = c.id WHERE  a.タグ名 = '食料品'  AND  b.タグ名 = '果物' GROUP BY  a.商品id;
  • 21. MongoDBのIndex 商品名 タグ 値段 ボールペン 日用品, 筆記用具 198 包丁 日用品, 刃物, キッチン 2980 バナナ 食料品, 果物 348 ほうれん草 食料品, 野菜 98 牛乳 食料品, 148 食料品で果物の商品 ■MongoDB  $all が使える   今の実装では最初の   要素のみIndex scan クエリー db.商品.find({  'タグ': { $all : ['食料品', '果物']} });
  • 22. MongoDBのIndex  主なIndex  ・配列へのIndex(tag)  ・複合Index  ・平面/球面座標Index  ・図形Index(交点,内包,近傍など各種検索)   ・円, 線, 多角形, etc  covered indexesも搭載  NoSQLの弱点を多機能なIndexで補う戦略
  • 23. 高スループット -26 -
  • 24. MongoDBのスループット 計測条件 ・3 core 3GB memory   ・構文解析込み(SQL, JS)   ・lo経由通信 (localhost) int(11)   ・1レコード、4kb程度 id int(11) PRI value0 value1 int(11)   ・1,000,000 レコード value2 int(11) value3 varchar(50) value4 varchar(50)     = 4GB value5 varchar(50) value6 varchar(50) value7 varchar(255)   ・11 column value8 int(11) value9 text   ・MySQLはInnoDB      
  • 25. MongoDBのスループット Insert ・MySQL : 345 sec (5m 45s)  ・MongoDB : 123 sec (2m 03s)  ・(MyIsam ) : 240 sec (4m 00s)
  • 26. MongoDBのスループット  Range fetch (10,000件 x 100) SELECT ・MySQL : 202 sec * FROM  ・MongoDB : 3.7 sec mytbl WHERE id BETWEEN 0 AND 9999;  Range count (10,000件 x 100) ・MySQL : 37 sec SELECT COUNT(*)  ・MongoDB : 0.4 sec FROM mytbl       WHERE id BETWEEN 0 AND 9999;
  • 27. MongoDBのスループット  MongoDB 範囲検索は特に速い!   ・B-tree実装が良い  Countが速い!   ・カーソルの両端を先に見る Read >>> Write な WEBシステムに最適      
  • 28. 並列性 -31 -
  • 29. MongoDBの並列性  MongoDBは2つのスケールアウト方式   が用意されている  ・Replica-set(ミラーリング) Read系の並列化、対障害性  ・Sharding(パーティショニング)    Write系の並列化、大量データ対策
  • 30. Replica-set -33 -
  • 31. replica-set Primary: 書き込み可能ノード Secondary:  読み取り専用ノード 全てのノードは同じデータを持っている Primary 同期 Secondary Secondary Secondary Secondary -34 -
  • 32. replica-set Primary: 書き込み可能ノード Secondary:  読み取り専用ノード Primaryが死んでも自動Failover Primary Primary 昇格 同期 Secondary Secondary Secondary Secondary -35 -
  • 33. replica-set Primary: 書き込み可能ノード Secondary:  読み取り専用ノード 自動Failoverではsplit brainが怖いのでvotingで対策 (以下の例では4/5 で当選) Primary Primary 投票 Secondary Secondary Secondary Secondary -36 -
  • 34. replica-set www.mongodb.jp httpd PHP mongo A mongo B mongod secondary mongod primary replica-set
  • 35. replica-set www.mongodb.jp www.mongodb.jp httpd httpd PHP PHP mongo A mongo B mongo C mongod secondary mongod primary mongod secondary replica-set
  • 36. Sharding -39 -
  • 37. Sharding mongos:クエリーゲートウェイ       mapping情報に基づき振り分ける config: mapping情報を保持 key = 'abc' key = 'xyz' mongos config config config key => replicaset map a.. ~ hz.. => Replica-set1 ia.. ~ rc.. => Replica-set2 rd..~ z.. => Replica-set3 Replica-set1 Replica-set2 Replica-set3 -40 -
  • 38. Sharding  RDBMSのパーティショニングと同じ発想  複数のReplica-setを束ねるイメージ  並列性や冗長性はReplica-setに任せる  Shardingキーの選択さえ適切ならば  Auto migrationでデータを適度に分散  
  • 39.  詳細はコチラ Sharding
  • 40. MongoDBの並列性  Read負荷が高いならReplica-set   MongoDBは元々高速なので殆どの問題は   Secondaryを増やせば解決する  Write負荷やデータ量の問題はSharding   Write負荷 :非時系列のShard-key   データ量 :時系列Shard-key         (扱いやすいから)
  • 41. トランザクションが無い -44 -
  • 42. MongoDBの排他  Webシステムでは、殆どの場合   トランザクションを使わない。使えない。  HTTPはstatelessなプロトコルで  statefulなトランザクションと相性が悪い。   掛けたまま帰っちゃう!   いつ戻って来るのか?   もう来ないのか?     不明!!
  • 43. MongoDBの排他  とはいえ、ある程度の排他処理は必要  NoSQLでは楽観ロックが主流   並列化を目指すと悲観ロックは機能しない    memcached の CASが有名   (Check and Set)
  • 44. MongoDBの排他 CAS  1. aがデータAをget A (cas=1)   memcached A (cas=1)
  • 45. MongoDBの排他 CAS  1. aがデータAをget A (cas=1)  2. ほぼ同時にbがデータAをget   A (cas=1)   楽観ロックなので 取れて良い memcached A (cas=1)
  • 46. MongoDBの排他 CAS  1. aがデータAをget A (cas=1)  2. ほぼ同時にbがデータAをget   A (cas=1)  3. aがデータAを更新   A' (cas=1) memcached cas値が一致する ので更新成功 A (cas=1) A' (cas=2)
  • 47. MongoDBの排他 CAS  1. aがデータAをget  2. ほぼ同時にbがデータAをget   A (cas=1)  3. aがデータAを更新  4. bがデータAを更新 A''(cas=1) memcached A' (cas=2) cas値が不一致で 更新失敗
  • 48. atomic操作 -51 -
  • 49. atomic操作  MongoDBにはCASが無い   もっと強力なatomic操作がある  特に便利なatomic操作  $inc   フィールドをインクリメントする  $setOnInsert   upsertの際、insert時だけ値を設定する
  • 50. 簡易CAS GET data1 = db.myData.findOne({ _id : 'FOO' }); PUT db.myData.update({ _id: data1._id,  cas: data1.cas },{ $inc : { cas : 1 }, $set { field1 : 'updated' } }); CASの実装は簡単  ・update時に常にcas値を1つ増加させる。  ・update時のクエリにドキュメントのcas値を使えば   衝突した際にはcas値が合わずupdateが失敗する -53 -
  • 51. atomic操作  配列系のatomic操作  $pop / $pullAll / $pull   配列フィールドから値を削除  $pushAll / $push   配列フィールドに値を追加  capped array   配列フィールドに値を追加する際    任意の配列長に保つよう切り捨てる機能
  • 52. findAndModify -55 -
  • 53. atomic操作  MongoDBにはfindAndModifyがある  findAndModify   atomicにデータ取得と更新が出来る   ≒ SELECT ~ FOR UPDATE    +UPDATE    +COMMIT or ROLLBACK
  • 54. 簡易MQ インデックス db.myMQ.ensureIndex({ tm: 1 }); 投入(アプリ)側 db.myMQ.save({  tm: 0,  Jobデータ }); ワーカー側 db.myMQ.findAndModify({ query: { tm : 0 },  update: { $set : { tm : 1 }} }); tm = 0 のドキュメントを拾うと同時にtm = 1 に更新してしまう。 他のワーカに拾われないという寸法! -57 -
  • 55. 簡易Jobスケジューラ インデックス db.myMQ.ensureIndex({ tm:1 }); 投入(アプリ)側 db.myMQ.save({  tm: Number(ISODate())+3600,  Jobデータ }); ワーカー側 db.myMQ.findAndModify({ query: { tm : { $lte :Number(ISODate())}},  update: { $set : { tm : Number.MAX_VALUE }} }); tm に時刻(3600秒後)を入れれば、狙った時間にFireできる。 $inc : 3600の様にすれば定期的なJobにも出来る。 結構自由自在! -58 -
  • 56. 簡易MapReduce ■単純なJobキュー ■MapReduce -59 -
  • 57. Monmoちゃん -60 -
  • 58. Monmoちゃん  findAndModifyを上手く使って   MapReduce環境を作ってみた。  V8 が優秀で思ったより使える!    MongoDB 以外何も要らない   (ロジックはDBの外で動作)
  • 59. ついでに -62 -
  • 60. MapReduce MongoDB付属のMapReduceは危険 Primaryで処理が走る ● 『DBでロジックが走る』ってどうなの? 並列化が出来ない ● NaN等で下手打つとDBが死ぬ ● 原則noscriptが基本!! -63 -
  • 61. Joinが出来ない -64 -
  • 62. Join あきらめよう・・・ -65 -
  • 63. MongoDB 何に使おう? -66 -
  • 64. まとめ  ・Readが非常に高速  ・多機能なIndex  ・高い並列性(&対障害性)  ・高い拡張性   WEBシステムのバックエンドDBに最適    DBキャッシュ層を省略し    システムを簡略化できる
  • 65. まとめ  ・多機能なIndex    配列Index(タグそのもの)   タグ機能    DB自体に機能があるので    特別なコードが必要ない
  • 66. まとめ  ・多機能なIndex    geohash :2次元座標Index    3dsphere :球面座標Index   地図機能 近隣の施設検索などがDBで完結
  • 67. まとめ  ・強力なAtomic操作機能  ・対障害性   MQなど非同期系のバックエンドにも良い    システム間のセマフォ的な使い方ができる    非Javaへの親和性も貴重   
  • 68. 最後に地雷の話 -71 -
  • 69. 地雷の話  ■必須オプション   ・notablescan   ・noscript  ■難易度が高い機能   ・Sharding  ■地雷機能   ・MapReduce   ・Aggregate   ・Textサーチ   ・Background indexing  ■チューニングポイント   ・oplog   ・migration (Sharding)   ・コネクション数
  • 70. 地雷の話  確かにMongoDBには幾つか地雷がある   (そして踏み易い)  巷にあるネガティブな情報は   地雷の爆発した跡     正しい使い方をすれば機能的にも性能的にも   非常に優秀なプロダクト
  • 71. おしまい   有難う御座いました。