Slide 1

Slide 1 text

݄ؒ10ԯPV͔ΒֶΜͩ
 MongoDBΞϯνύλʔϯ db tech showcase ౦ژ 2014 speaker: “Yuji Isobe”

Slide 2

Slide 2 text

history: [
 “violinist”
 “engineer”
 “security specialist”
 “socket.io contributor”
 “startup member
 of ZenClerk ”
 ] name: “Yuji Isobe”

Slide 3

Slide 3 text

questions: -> MongoDBΛ࢖༻ͨ͜͠ͱ͕͋Γ·͔͢ʁ -> ຊ൪؀ڥͰMongoDBΛ࢖༻͍ͯ͠·͔͢ʁ

Slide 4

Slide 4 text

goal: -> ZenClerk͕݄ؒ10ԯPVΛࢧ͑Δ·Ͱͷ
 աఔͰܦݧͨ͠ΞϯνύλʔϯΛ঺հ -> ओʹύϑΥʔϚϯενϡʔχϯάͷ࿩ ->ʮ݄ؒ10ԯPVΛࢧ͑ΔMongoDBʯͷͦͷઌ IUUQXXXTMJEFTIBSFOFUZVKJPTBLBQWNPOHPEC

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

ϦΞϧλΠϜ

Slide 7

Slide 7 text

ϦΞϧλΠϜ෼ੳ Ϗοάσʔλ

Slide 8

Slide 8 text

db.ZenClerk .stats() -> ݄ؒ10ԯPV -> ඵؒ400PV -> ಉ࣌઀ଓ਺5ສ -> ݄ؒ10TBอଘ

Slide 9

Slide 9 text

architecture: front-end: [ “AngularJS” “Ruby on Rails” “MySQL” “memcached”
 “AWS” ] back-end: [ “Node.js”
 “MongoDB” “socket.io” “Redis”
 “AWS” ]

Slide 10

Slide 10 text

architecture: front-end: [ “AngularJS” “Ruby on Rails” “MySQL” “memcached”
 “AWS” ] back-end: [ “Node.js”
 “MongoDB” “socket.io” “Redis”
 “AWS” ]

Slide 11

Slide 11 text

i2.2xlarge m1.large m3.large db.ZenClerk .aggregate() r3.large

Slide 12

Slide 12 text

ʙ1000ສPV mogngod

Slide 13

Slide 13 text

1000ສʙ1ԯPV delayed replica replica set

Slide 14

Slide 14 text

1ԯPVʙ10ԯPV replica set shard mongos replica set shard replica set shard delayed replica delayed replica delayed replica mongoc

Slide 15

Slide 15 text

͜͜·ͰΞϓϦέʔγϣϯͷมߋ
 ΄ͱΜͲͳ͠ʢҰ෦ΫΤϦΛ࠷దԽʣ

Slide 16

Slide 16 text

we.use(“MongoDB”).explain() -> εΩʔϚϨε -> τϥϯβΫγϣϯෆཁ
 ʢ࠷௿ݶͷΞτϛοΫૢ࡞ʣ -> ॊೈͳΫΤϦ -> ༰қͳεέʔϧΞ΢τ
 -> Node.jsͱͷ૬ੑͷྑ͞

Slide 17

Slide 17 text

we.use(“MongoDB”).explain(true) -> ಋೖͷ༰қ͞ʢϗεςΟϯάαʔϏε༗ແʣ -> ֶशͷ༰қ͞ʢΤϯδχΞҎ֎ʹͱͬͯ΋ʣ

Slide 18

Slide 18 text

ࠓ೔࿩͢ͷ͸ɾɾɾ ϕετϓϥΫςΟε Ξϯνύλʔϯ

Slide 19

Slide 19 text

ͪ͜Βʂ ϕετϓϥΫςΟε Ξϯνύλʔϯ

Slide 20

Slide 20 text

Ͱ΋ͦͷલʹɾɾɾ

Slide 21

Slide 21 text

ϕετϓϥΫςΟε

Slide 22

Slide 22 text

εΩʔϚσβΠϯ -> TwitterͷλΠϜϥΠϯΛอଘ͢Δ -> RDBMSͳΒਖ਼نԽ -> MongoDBͷϕετϓϥΫςΟε͸ʁ

Slide 23

Slide 23 text

-> ಡΈࠐΈॏࢹ -> 1ΫΤϦ1ώοτ -> ίϝϯτ਺ʹԠͯ͡
 ॻ͖ࠐΈ͕ॏ͘ͳΔ υΩϡϝϯτΛຒΊࠐΉ session:
 _id: “session_id”
 device: “iPhone”
 page_views: [
 {url: “/items/1”}
 ] timeline:
 _id: “yujiosaka”
 tag: “#dbtechshowcase”
 tweets: [
 {text: “MongoDB Rocks!”}
 ]

Slide 24

Slide 24 text

-> ॻ͖ࠐΈॏࢹ -> 2ΫΤϦN+1ώοτ -> ॻ͖ࠐΈ͸εέʔϧ͢Δ υΩϡϝϯτΛຒΊࠐ·ͳ͍ session:
 _id: “session_id”
 device: “iPhone”
 page_views: [
 {url: “/items/1”}
 ] timeline:
 _id: “yujiosaka”
 tag: “#dbtechshowcase” ! tweet: _id: 1234
 user_id: “yujiosaka”
 text: “MongoDB Rocks!”

Slide 25

Slide 25 text

timeline:
 _id: “yujiosaka-20141111”
 tag: “#dbtechshowcase”
 tweets: [
 {text: “MongoDB Rocks!”}
 ] -> όϥϯεܕ -> 1ΫΤϦ೔਺෼ώοτ -> ॻ͖ࠐΈ͸1೔෼·Ͱ
 ͔͠ॏ͘ͳΒͳ͍ ϋΠϒϦου

Slide 26

Slide 26 text

εΩʔϚϨε ≠ εΩʔϚఆ͕ٛෆཁ RDBMSΑΓ΋બ୒ࢶ͕ଟ͘೉͍͠ tips: IUUQXXXNPOHPECDPNQSFTFOUBUJPOTTDIFNBEFTJHOTDBMF

Slide 27

Slide 27 text

Ξϯνύλʔϯ

Slide 28

Slide 28 text

ΠϯσοΫεฤ ΫΤϦฤ Ξοϓσʔτฤ ΞʔΩςΫνϟฤ

Slide 29

Slide 29 text

ᶃΠϯσοΫεͷషΓա͗

Slide 30

Slide 30 text

MongoDB͸ϝϞϦͷ࢖͍ํ͕
 ͋·Γݡ͋͘Γ·ͤΜ

Slide 31

Slide 31 text

before: user = new mongoose.Schema first: {type: String, required: true, index: true} last: {type: String, required: true, index: true} city: {type: String, required: true, index: true} ... created_at: {type: Date, default: Date.now, index: true} ! ॻ͖ࠐΈ͕٘ਜ਼ʹͳͬͯ΋ಡΈࠐΈ͕ૣ͚Ε͹͍͍͡ΌΜʂ

Slide 32

Slide 32 text

after: user = new mongoose.Schema first: {type: String, required: true} last: {type: String, required: true} city: {type: String, required: true} ... created_at: {type: Date, default: Date.now} ! ॻ͖ࠐΈ͕٘ਜ਼ʹͳͬͯ΋ಡΈࠐΈ͕ૣ͚Ε͹͍͍͡ΌΜʂ

Slide 33

Slide 33 text

ಡΈࠐΈ΋ɺΠϯσοΫε͕ ϝϞϦʹ৐Βͳ͚Ε͹஗͘ͳΔ

Slide 34

Slide 34 text

tips: όʔδϣϯ2.8ʹPluggable Storage
 Engine͕༧ఆ͞Ε͍ͯΔͷͰɺ ݡ͍Τϯδϯ͕બ΂ΔΑ͏ʹͳΔ https://blog.compose.io/the-coming-of-the-mongodb-storage-engines/

Slide 35

Slide 35 text

ᶄจࣈྻͷΠϯσοΫε

Slide 36

Slide 36 text

ΠϯσοΫεͷߏ଄ -> RDBMSͱ΄ͱΜͲಉ͡ -> ΠϯσοΫεʹB-TreeΛ࠾༻ -> B-Tree͸ৗʹฏߧΛอ͍ͬͯΔ

Slide 37

Slide 37 text

จࣈྻͷΠϯσοΫε -> ϗοτσʔλ͕෼ࢄ -> ϝϞϦޮ཰͕ѱ͍

Slide 38

Slide 38 text

࣌ؒɾObjectIdͷΠϯσοΫε -> ϗοτσʔλ͕ूத -> ϝϞϦޮ཰͕ྑ͍

Slide 39

Slide 39 text

tips: Ͱ͖Δ͚ͩObjectIdΛ࢖͍·͠ΐ͏ ޙ͔Βͷஔ͖׵͑͸େมͰ͢

Slide 40

Slide 40 text

ΠϯσοΫεฤ ΫΤϦฤ Ξοϓσʔτฤ ΞʔΩςΫνϟฤ

Slide 41

Slide 41 text

ᶅϑΟʔϧυΛࢦఆ͠ͳ͍ΫΤϦ

Slide 42

Slide 42 text

Ϣʔβʔ৘ใͷ͏ͪ ౎ࢢ৘ใ͚͕ͩཉ͍͠ user: {_id: “yujiosaka”, first: “Yuji”, last: “Isobe”, city: “Tokyo”} index: {_id:1, city: 1} // compound index

Slide 43

Slide 43 text

ϑΟʔϧυࢦఆͳ͠ -> SQLͰͷʮselect *ʯ -> ෆཁͳωοτϫʔΫίετ -> ෆཁͳσΟεΫΞΫηε var user = db.users.findOne({_id: “yujiosaka”});

Slide 44

Slide 44 text

ϑΟʔϧυࢦఆ͋Γ -> SQLͰͷʮselect cityʯ -> ωοτϫʔΫίετͷઅ໿ -> covered index ͕׆༻Ͱ͖Δ var user = db.users.findOne({_id: “yujiosaka”}, {city: 1});

Slide 45

Slide 45 text

tips: covered indexΛ༗ޮ׆༻͢Ε͹ɺ
 σΟεΫ΁ͷΞΫηεҰ੾ͳ͠ʹ
 ϝϞϦ͚͔ͩΒ৘ใΛಡΈࠐΊΔ

Slide 46

Slide 46 text

ᶆίʔϧυσʔλ΁ͷΫΤϦ

Slide 47

Slide 47 text

MongoDBͷಛ௃ -> ϗοτσʔλ΁ͷΞΫηε͸ߴ଎ -> ίʔϧυσʔλ΁ͷΞΫηε͸஗͍ -> શσʔλ΁ͷΞΫηε͸ۤख

Slide 48

Slide 48 text

ZenClerkʹ͓͚Δूܭ -> 5෼͝ͱʹσʔλΛཁ໿ -> 1࣌ؒ͝ͱʹ౷ܭσʔλΛूܭ -> 1೔͝ͱʹ౷ܭσʔλΛूܭ

Slide 49

Slide 49 text

tips: ৗʹϗοτσʔλΛҙࣝͨ͠
 ࢖͍ํΛ͠·͠ΐ͏

Slide 50

Slide 50 text

ᶇϓϥΠϚϦʹภͬͨΫΤϦ

Slide 51

Slide 51 text

ϨϓϦΧηοτ -> ΫΤϦΛ෼ࢄͤ͞Δ͜ͱ͕Ͱ͖Δ -> ηΧϯμϦʹΫΤϦΛ౤͛Δ͔͸
 ϓϩάϥϚ͕ܾΊΒΕΔ -> σϑΥϧτͰ͸ϓϥΠϚϦʹ౤͛ΒΕΔ

Slide 52

Slide 52 text

σϑΥϧτ -> ϓϥΠϚϦ͔Βಡ·ΕΔ -> ࠷৽ͷσʔλ͕อো͞ΕΔ var user = db.users.find({city: “Tokyo”});

Slide 53

Slide 53 text

ηΧϯμϦΛࢦఆ -> ηΧϯμϦ͕͋Ε͹ηΧϯμϦ͔Βɺ
 ͳ͚Ε͹ϓϥΠϚϦ͔Βಡ·ΕΔ -> ࠷৽ͷσʔλ͸อো͞Εͳ͍ var user = db.users.find({city: “Tokyo”})
 .readPref("secondaryPreferred")

Slide 54

Slide 54 text

tips: σʔλ͕࠷৽Ͱͳͯ͘΋Α͍৔߹͸
 ಡΈࠐΈΛηΧϯμϦʹ޲͚Δ͜ͱͰ
 ΫΤϦ͕෼ࢄ͢Δ IUUQTTQFBLFSEFDLDPNNPOHPECQSBDUJDBM TDBMJOHBOETIBSEJOHFMJPUIPSPXJU[HFO

Slide 55

Slide 55 text

ΠϯσοΫεฤ ΫΤϦฤ Ξοϓσʔτฤ ΞʔΩςΫνϟฤ

Slide 56

Slide 56 text

ᶈඇޮ཰ͳΞοϓσʔτ

Slide 57

Slide 57 text

Α͘ݟ͔͚Δίʔυᶃ -> ඞͣΫΤϦ͕࣮ߦ͞ΕΔ -> ແବͳωοτϫʔΫίετ -> ඇΞτϛοΫͳॲཧ var user = db.users.findOne({_id: “yujiosaka”}); user.count += 1; user.save();

Slide 58

Slide 58 text

Α͘ݟ͔͚Δίʔυᶃ -> updateͱ$incΛ࢖ͬͯ·ͱΊΒΕΔ -> 1ճͷΞοϓσʔτͰࡁΉ -> ΞτϛοΫͳॲཧ db.users.update({_id: “yujiosaka”}, {$inc: {count: 1}});

Slide 59

Slide 59 text

Α͘ݟ͔͚Δίʔυᶄ -> σʔλ͕ݟ͔ͭͬͨΒߋ৽͠ɺݟ͔ͭΒͳ͔ͬͨΒ࡞੒͢Δ -> Ұݟෳࡶͳίʔυ var user = db.users.findOne({_id: “yujiosaka”}); if (user) { user.count += 1;
 user.save(); } else { db.users.insert({_id: “yujiosaka”, count: 1}); }

Slide 60

Slide 60 text

-> {upsert: true} Λ࢖͏ͱ·ͱΊΒΕΔ -> ΑΓγϯϓϧͳίʔυ Α͘ݟ͔͚Δίʔυᶄ db.users.update({_id: “yujiosaka”}, {$inc: {count: 1}}, {upsert: true});

Slide 61

Slide 61 text

ᶉංେԽ͢ΔυΩϡϝϯτ

Slide 62

Slide 62 text

Ϛ΢εͷ࠲ඪσʔλΛ
 อଘ͢Δ behavior: points: [{x: 151, y: 100} {x: 151, y: 179} {x: 151, y: 266} … {x: 151, y: 340}]

Slide 63

Slide 63 text

MongoDBͷۤख෼໺ -> ϑΟʔϧυ͕ංେԽ͢ΔΞοϓσʔτ͕஗͍ -> σʔλ͕ҰఆͷαΠζʹऩ·Βͳ͘ͳΔͱ
 σΟεΫ಺ͰσʔλͷҠಈ͕ى͖Δ -> RedisͰMongoDBͷۤख෼໺Λิ͏

Slide 64

Slide 64 text

Redis -> ΦϯϝϞϦܕͷKVS -> ಡΈࠐΈɾॻ͖ࠐΈ͕ૣ͍ -> جຊతʹσʔλͷӬଓԽ͸͠ͳ͍ -> σʔλܕ͕ඇৗʹ๛෋
 ʢϦετɾηοτɾϋογϡʣ

Slide 65

Slide 65 text

RedisΛ࢖Θͳ͍৔߹ db.col.update({_id: 1234}, {$push: {points: {x: 151, y: 100}});
 db.col.update({_id: 1234}, {$push: {points: {x: 151, y: 179}});
 db.col.update({_id: 1234}, {$push: {points: {x: 151, y: 266}});
 …
 db.col.update({_id: 1234}, {$push: {points: {x: 151, y: 340}}); -> ࠲ඪ͕Ҡಈ͢ΔͨͼʹMongoDBʹॻ͖ࠐ·ΕΔ -> αΠζ͕ऩ·Γ੾Βͳ͍ͱɺσʔλͷҠಈ͕ى͖Δ

Slide 66

Slide 66 text

RedisΛ࢖ͬͨ৔߹ db.col.insert({points: [
 {x: 151, y: 100},
 {x: 151, y: 179},
 {x: 151, y: 266},
 …
 {x: 151, y: 340}
 ]}); -> Ұ౓͔͠MongoDBʹॻ͖ࠐ·ͳ͍ -> υΩϡϝϯυͷαΠζ͸͜ΕҎ্େ͖͘ͳΒͳ͍

Slide 67

Slide 67 text

tips: ͢΂ͯΛMongoDB͚ͩͰ΍Ζ͏ͱͤͣɺ
 ۤखͳ෦෼͸ଞͷٕज़Ͱิ͏͜ͱ͕େ੾

Slide 68

Slide 68 text

ΠϯσοΫεฤ ΫΤϦฤ Ξοϓσʔτฤ ΞʔΩςΫνϟฤ

Slide 69

Slide 69 text

ᶊ٧ΊࠐΈա͗DB

Slide 70

Slide 70 text

σʔλΛҰͭͷDBʹ٧ΊࠐΜͰ
 ྑ͍͜ͱ͸ʢࠓͷͱ͜Ζʣ͋·Γͳ͍

Slide 71

Slide 71 text

ͳͥDBΛ෼͚Δͷ͔ʁ -> Reader-WriterϩοΫ͕࢖ΘΕ͍ͯΔ -> 2.2.0Ҏ߱͸DB୯ҐͰϩοΫ͢Δ -> ϚγϯΛ෼͚Ε͹ϝϞϦ͕૿͑Δ

Slide 72

Slide 72 text

ZenClerk ʹ͓͚ΔDBͷ༻్ -> ϝΠϯσʔλʢHotʣ -> ϝΠϯσʔλʢColdʣ -> ੜσʔλ -> ܭࢉ݁Ռσʔλ -> ౷ܭσʔλ -> αΠτଐੑσʔλ

Slide 73

Slide 73 text

tips: όʔδϣϯ2.8ʹdocument-level locking 3.0Ҏ߱ʹpartitioned joins͕༧ఆ͞Ε͍ͯΔ
 ʢޙऀ͸͋·Γ͋ͯʹ͠ͳ͍ํ͕ແ೉ͦ͏ʣ http://www.slideshare.net/tetsutarowatanabe/mongodb-world-2014-37081258

Slide 74

Slide 74 text

ᶃΠϯσοΫεͷషΓա͗ ᶄจࣈྻͷΠϯσοΫε ᶅϑΟʔϧυΛࢦఆ͠ͳ͍ΫΤϦ ᶆίʔϧυσʔλ΁ͷΫΤϦ ᶇϓϥΠϚϦʹภͬͨΫΤϦ ᶈඇޮ཰ͳΞοϓσʔτ ᶉංେԽ͢ΔυΩϡϝϯτ ᶊ٧ΊࠐΈա͗DB Ξϯνύλʔϯ͓͞Β͍

Slide 75

Slide 75 text

Ξϯνύλʔϯʹ
 ؕΒͳ͍ͨΊʹ

Slide 76

Slide 76 text

̏ͭͷ؂ࢹ -> ϦΞϧλΠϜ؂ࢹ -> ݟฦͨ͢Ίͷ؂ࢹ -> ஗͍ΫΤϦͷ؂ࢹ

Slide 77

Slide 77 text

ϦΞϧλΠϜ؂ࢹ

Slide 78

Slide 78 text

-> ComposeʢMongoHQʣμογϡϘʔυ -> ݱࡏͷ݈߁νΣοΫ༻ -> ࣾ಺ʹઐ༻σΟεϓϨΠΛઃஔ -> ҟৗ͕͋Ε͹ʮ୭͔Mongoࡴͨ͠ʁʯ ϦΞϧλΠϜ؂ࢹ

Slide 79

Slide 79 text

ݟฦͨ͢Ίͷ؂ࢹ

Slide 80

Slide 80 text

-> MMSμογϡϘʔυ
 -> ఆظతͳ݈߁਍அ -> ো֐ൃੜ࣌ʹݟฦͯ͠
 ɹʮͳΜͰ͜ΜͳϩοΫߴ͘ͳͬͯΜͷʁʯ ݟฦͨ͢Ίͷ؂ࢹ

Slide 81

Slide 81 text

஗͍ΫΤϦͷ؂ࢹ

Slide 82

Slide 82 text

-> explain(true) -> system.profile.find() -> Dex -> Compose (MongoHQ) Slow Queries ஗͍ΫΤϦͷ؂ࢹ

Slide 83

Slide 83 text

tips: ObjectIdΛ࢖ͬͨΫΤϦʹ 100msҎ্͔͔ͬͨΒةݥ৴߸

Slide 84

Slide 84 text

my.presentation.aggregate() -> MongoDB͸બ୒ࢶ͕ଟ͍ -> Ξϯνύλʔϯ͸͍͔ͭ͘ଘࡏ͢Δ -> ΞϯνύλʔϯʹؕΒͳ͍ͨΊʹ؂ࢹ͢Δ -> ࠷৽৘ใͷΩϟονΞοϓ΋ॏཁ

Slide 85

Slide 85 text

͍͞͝ʹ

Slide 86

Slide 86 text

we.are “hiring! :)” https://www.zenclerk.com/recruit.html

Slide 87

Slide 87 text

any.questions?