Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

後悔しないもんごもんごの使い方 〜アプリ編〜

8,598 views

Published on

BPStudy 71回で発表した、MongoDBのアプリ寄りの使い方の話。

Published in: Technology

後悔しないもんごもんごの使い方 〜アプリ編〜

  1. 1. 後悔しない もんごもんごの使い方 ∼アプリ編∼ 松下 雅和(@matsukaz)
  2. 2. 自己紹介 •松下 雅和 •サーバ寄りのエンジニア •Twitter: @matsukaz •あだな:まつかず •DevLOVE スタッフ
  3. 3. 今日の話 •開発しやすいってほんと? •おすすめライブラリ (Java/Node.jsの話) •データ設計はどうやるの? •こういう使い方するといいかも
  4. 4. 開発しやすいって ほんと?
  5. 5. ほんとだよ!
  6. 6. 公式ドキュメントにも MongoDB is an open-source, document- oriented database designed for ease of development and scaling. MongoDBは、開発しやすさとスケールしやすさを目 指したオープンソースのドキュメント指向DBです。 と書いてある
  7. 7. 開発しやすい ポイント①
  8. 8. インストールが簡単!
  9. 9. 環境ごとのファイルを DLして展開するだけ もろもろの パッケージにも対応
  10. 10. あとは起動するだけ $ bin/mongod --fork --dbpath ./data --logpath ./logs/mongod.log ※ 必要最小限なオプションのみ
  11. 11. なにこれ 簡単すぎ…? @mongodb >>あなたの適正もんごは?
  12. 12. 開発しやすい ポイント②
  13. 13. スキーマレス
  14. 14. どころか、 DBやコレクションの 作成も不要 (勝手に作られる)
  15. 15. $ bin/mongo > use db1; // 操作するとDBが作られる switched to db db1 // collectionが存在しなかったら作られる > db.user.save( { name : "matsukaz" } );
  16. 16. つまり 簡単に使う分には DB側の準備が 全くいらない
  17. 17. まぢかよもんご!!!! クールすぎるぜもんご! そこにしびr(ry
  18. 18. 開発しやすい ポイント③
  19. 19. ドキュメント指向
  20. 20. RDBでやってた 正規化とか めんどくない?
  21. 21. 階層構造で持てるなら 非正規化のままでも いいんでない?
  22. 22. プログラム上の オブジェクト構造を そのまま永続化も 可能だし
  23. 23. 試しに Node.jsで実装してみる
  24. 24. $ npm install mongodb # ドライバーのインストール $ vi index.js $ node index.js # 実行 { name: 'matsukaz', _id: 51f7efbed66a41de0f000001 } var MongoClient = require("mongodb").MongoClient; var url = "mongodb://127.0.0.1:27017/db1"; var data = {name : "matsukaz", age : 34}; // 作成したデータ MongoClient.connect(url, function(err, db) { // 接続 var userColl = db.collection("user"); userColl.save(data, function(err) { // データを保存 userColl.findOne({name: "matsukaz"}, function(err, user) { // 名前で検索 console.log(user); process.exit(0); }); }); });
  25. 25. こんだけ簡単だと 使わない手はないよね!
  26. 26. おすすめライブラリ
  27. 27. Java •mongo-java-driver • https://github.com/mongodb/mongo-java-driver •MongoDBの公式ドライバー •ローレベルAPIなので操作はかなり面倒
  28. 28. Java •mongo-java-driver •コネクションプールのチューニングは必須 項目 意味 値 connectionsPerHost コネクション数 100 threadsAllowedToBlockForC onnectionMultiplier 1コネクション辺りの接続 待ち数 4 •上記の例だと、プールの上限は 100 + (100 * 4) = 500
  29. 29. Java •Spring Data - MongoDB • http://www.springsource.org/spring-data/mongodb •ドキュメントとPOJO間マッパー •mongo-java-driverを内部で利用 public class User { private String id; private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } // 各プロパティのgetter } MongoTemplate mongoTemplate = new MongoTemplate(new Mongo(url), "dbname"); // ドキュメント作成 mongoTemplate.insert(new User("matsukaz", 34)); // ドキュメント取得 User matsukaz = mongoTemplate.findOne( new Query(Criteria.where("name").is("matsukaz")}, USer.class);
  30. 30. Javaでも 言うほど相性は 悪くない
  31. 31. Node.js •node-mongodb-native • https://github.com/mongodb/node-mongodb-native •MongoDBの公式ドライバー •スキーマ定義が不要ならこれで require("mongodb").MongoClient.connect(url, function(err, db) { var userCollection = db.collection("user"); // ドキュメント作成 userCollection.save({name:"matsukaz", age:34}, function(err){ // ドキュメント取得 userCollection.findOne({name: "matsukaz"}, function(err, docs){ console.log(docs); }); }); });
  32. 32. Node.js •Mongoose • http://mongoosejs.com •ドキュメントとオブジェクト間マッパー •node-mongodb-nativeを内部で利用 var db = require("mongoose").connect(url); // スキーマ定義が必要 var User = db.model("user", new Schema({ name : { type : String, unique : true}, age : Number })); var matsukaz = new User({name:"matsukaz", age:34}); matsukaz.save(function(err) { // ドキュメント作成&取得 User.findOne({name:"matsukaz"}, function(err, user){ console.log(user); }); });
  33. 33. Node.jsと 本当に相性がいい!
  34. 34. MongoDBを使うと 「開発がしやすくなる」 のは伝わりました?
  35. 35. んでは次、
  36. 36. データ設計は どうやるの?
  37. 37. 開発は簡単だけど、 何も考えずに データ構造を決めると 運用で死にます・・・
  38. 38. データ構造を決める上で 大事なポイントを整理
  39. 39. BSONの特徴に合わせる •BSONは複雑なデータ構造を扱える •RDBとは違い、積極的に階層化/非正規化 { "facebookId" : xxx, "status" : { "lv" : 10, "coin" : 9999, ... }, "layerInfo" : "1¦1¦0¦1¦2¦1¦1¦3¦1¦1¦4¦0...", "structure" : { "1¦1" : { "id" : xxxx, "depth" : 3, "width" : 3, ... }, "4¦8" : { "id" : xxxx, "depth" : 2, "width" : 2, ... } }, "neighbor" : [ { "id" : xxx, ... }, { "id" : xxx, ... } ] }
  40. 40. BSONの特徴に合わせる •スキーマレス = データ構造の変更が容易 •開発を進めながら最適な構造にしていく •後方互換性も意識する { "dataId" : xxx, "update" : { "user" : xxx, "time" : xxx, "from" : "API" } } { "dataId" : xxx, "updateUser" : xxx } { "dataId" : xxx, "update" : { "user" : xxx } } 互換性を保ち やすい構造で 項目の追加は 互換性が保ちやすい
  41. 41. BSONの特徴に合わせる •リレーションは、パフォーマンスも考えた上 で、利用の有無とやり方を検討 •独自IDを利用 •ObjectIdを利用 •DBRefを利用 { "userId" : 123, "manager" : 456 } { "userId" : 123, "manager" : ObjectId("4ba550e2b...") } { "userId" : 123, "manager" : DBRef("user", ObjectId("4ba550e2b...")) }
  42. 42. データ型の差異に注意 •クライアントによっては、データ型のマッピン グが異なるので注意が必要 •コンソール(mongo) •import/exportツール •言語別のドライバー/ライブラリ
  43. 43. 苦手な部分は事前に考慮 •トランザクションはない前提で •1ドキュメントにおけるデータ量/フィールド 数が多すぎないように •場合によってはデータを圧縮 "layerInfo" : { "1¦1" : 0, "1¦2" : 1, ... } "layerInfo" : "1¦1¦0¦1¦2¦1¦1¦3¦1¦1¦4¦0..."
  44. 44. 苦手な部分は事前に考慮 •DBレベルのロックがかかる(v2.4時点)の で、アクセス頻度は極力減らす •場合によっては、同じシステム内のコレク ションでも、複数のDBに分割して保存する
  45. 45. シャードキーは慎重に •カーディナリティが低い値は使わない •利用頻度の高いデータがメモリ上に乗り、低い データはメモリ上に乗らないように •参照や更新が多いデータはバランスよく各 Shardに分散
  46. 46. シャードキーは慎重に •極力Targetedオペレーションにする •Shard Keyでデータを操作 •Shard Key以外の操作はIndexを利用 Operation Type db.foo.find( { ShardKey : 1 } ) Targeted db.foo.find( { ShardKey : 1, NonShardKey : 1 } ) Targeted db.foo.find( { NonShardKey : 1 } ) Global db.foo.insert( <object> ) Targeted db.foo.update( { ShardKey : 1 }, <object> ) db.foo.remove( { ShardKey : 1 } ) Targeted db.foo.update( { NonShardKey : 1 }, <object> ) db.foo.remove( { NonShardKey : 1 } ) Global
  47. 47. 気をつける点は それなりに多いけど、
  48. 48. もんごの特性を 理解していれば、 当たり前に考慮できる ようになる・・はず
  49. 49. まずは 使ってみることが 大事!!
  50. 50. 最後に、 こういう使い方すると いいかもという話
  51. 51. プロトタイプ開発 •複雑なデータ構造を簡単に扱えるので、開発ス ピード重視で作れる •スキーマレスなので、実装しながらデータ構造 を変更できる •ちょっとしたゲームのプロトタイプ開発 (+3回の仕様変更)が2週間で出来たよ
  52. 52. 開発中 •開発中は以下のような方法を取ることが多い •各自ローカルでMongoDBを起動して開発 •共用のMongoDBサーバを用意して用途別に DBを割り当てる •各自の開発用 •DEV環境用 •Jenkinsによる単体テスト用
  53. 53. 負荷テスト •コマンドラインツール(mongo)などから簡 単に大量データを投入 •chunk移動しまくるので落ち着くまで注意 > // 1000万件のテストデータを作成 > function pad(str, length) { str = String(str); while (str.length < length) str = "0" + str; return str; } > for (var i = 1; i <= 10000000; i++) { db.user.save({name: ("hoge" + pad(i, 10)) }); }
  54. 54. 障害テスト •障害を想定した動作検証は必ずやる。絶対。 •mongodが落ちた場合 •PRIMARYへ昇格するか •復帰後にデータが正しく同期されるか •mongocが落ちた場合に影響がないか •mongosが落ちた場合のシステムの挙動 •バックアップから戻せるか
  55. 55. まとめ •開発での利用はほんとに簡単! •とりあえず作ってみよう!という場面 で使えるのはもちろん •使いどころを間違えなければサービス でもちゃんと使える •もんごもんご!
  56. 56. 宣伝! •WEB+DB PRESS Vol.75 に 「MongoDB実践入門」を書 きました!
  57. 57. ご清聴 ありがとう ございました!

×