62
月間10億PVを 支えるMongoDB speaker: “Yuji Isobe”

月間10億pvを支えるmongo db

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 月間10億pvを支えるmongo db

月間10億PVを支えるMongoDB

speaker: “Yuji Isobe”

Page 2: 月間10億pvを支えるmongo db

name: “Yuji Isobe”

attributes: [ “engineer” “consultant” “security specialist” “startup member \ of ”]

Page 3: 月間10億pvを支えるmongo db

-> 2年間で月間10億PVを支える まで成長した の 「泥臭い」負荷対策をお話します-> あるある紹介-> 今はまだ問題点を洗い出している段階 ベストプラクティスがあれば教えて欲しい

goals:

Page 4: 月間10億pvを支えるmongo db
Page 5: 月間10億pvを支えるmongo db

大量データ

Page 6: 月間10億pvを支えるmongo db

大量データトラフィック急増

Page 7: 月間10億pvを支えるmongo db

-> 合計月間PV10億-> 秒間平均400PV-> 平均同時接続数5万-> 月間保存データ量10TB

db. .stats()

Page 8: 月間10億pvを支えるmongo db

back_ends: [ “Node.js” “CoffeeScript” “MongoDB” “Redis” “AWS”]

front_ends: [ “Nginx” “Ruby on Rails” “MySQL” “memcached” “AWS”]

architecture:

Page 9: 月間10億pvを支えるmongo db

back_ends: [ “Node.js” “CoffeeScript” “MongoDB” “Redis” “AWS”]

front_ends: [ “Nginx” “Ruby on Rails” “MySQL” “memcached” “AWS”]

architecture:

Page 10: 月間10億pvを支えるmongo db

we.use(“ ”).explain()

-> スキーマレス-> 安定した書き込み-> 柔軟なクエリ-> 容易なスケールアウト-> との相性の良さ

Page 11: 月間10億pvを支えるmongo db

月間10億PVへの道のり

-> ~3000万PV-> 3000万~1億PV-> 1億~3億PV-> 3億~10億PV-> 継続的な監視

Page 12: 月間10億pvを支えるmongo db

~3000万PVいいから

インデックスだ

!!!

Page 13: 月間10億pvを支えるmongo db

-> メモリ上に乗れば高速-> 1クエリにつき1インデックス-> B-Treeのバランスが重要

インデックスを理解する

Page 14: 月間10億pvを支えるmongo db

-> メモリ上に乗れば高速-> 1クエリにつき1インデックス-> B-Treeのバランスが重要

インデックスを理解する

From 2.6.0

Page 15: 月間10億pvを支えるmongo db

メモリ上に乗れば高速

Page 16: 月間10億pvを支えるmongo db

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}

書き込みが犠牲になっても読み込みが早ければいいじゃん!

Before

Page 17: 月間10億pvを支えるmongo db

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, index: true}

書き込みが犠牲になっても読み込みが早ければいいじゃん!

After

Page 18: 月間10億pvを支えるmongo db

メモリ上に乗らなければ遅くなる

Page 19: 月間10億pvを支えるmongo db

プログラムからフィールドを削除したが、インデックスを消し忘れ、無駄なインデックスが残る…

スキーマレスあるある

Page 20: 月間10億pvを支えるmongo db

1クエリにつき1インデックス

From 2.6.0

Page 21: 月間10億pvを支えるmongo db

db.users.ensureIndex({first:1});db.users.ensureIndex({last:1});

db.users.ensureIndex({ first:1, last:1});

indexintersection

compoundindex vs.

-> 複数の検索条件を 組み合わせたインデックス

-> 2つのインデックスを使った 検索結果の共通部分を返す

{first: “Yuji”, last: “Isobe”, city: “Osaka”}

From 2.6.0

Page 22: 月間10億pvを支えるmongo db

db.users.ensureIndex({first:1});db.users.ensureIndex({last:1});

db.users.ensureIndex({ first:1, last:1});

indexintersection

compoundindex vs.

-> 複数の検索条件を 組み合わせたインデックス

-> 2つのインデックスを使った 検索結果の共通部分を返す

{first: “Yuji”, last: “Isobe”, city: “Osaka”}

From 2.6.0

このクエリを早くしたい

Page 23: 月間10億pvを支えるmongo db

db.users.ensureIndex({first:1});db.users.ensureIndex({last:1});db.users.ensureIndex({ first:1, last:1});

indexintersection

compoundindex vs.

メリット-> 同時にいくつでも

デメリット-> 用途は限定的

メリット-> 柔軟な用途

デメリット-> 現在は同時に2つまで

2.6.0以降は消してしまってもいいかも知れません

From 2.6.0

Page 24: 月間10億pvを支えるmongo db

B-Treeのバランスが重要

Page 25: 月間10億pvを支えるmongo db

-> インデックスにB-Treeを採用-> B-Treeは常に平衡を保っている

インデックスの構造

Page 26: 月間10億pvを支えるmongo db

文字列のインデックス

-> Hotデータが分散-> メモリ効率が悪い

Page 27: 月間10億pvを支えるmongo db

ObjectId・時間のインデックス

-> Hotデータが集中-> メモリ効率が良い

Page 28: 月間10億pvを支えるmongo db

できるだけObjectIdを使いましょう後からの変更は大変です(経験談)

教訓

Page 29: 月間10億pvを支えるmongo db

Schema Design at Scale

http://www.mongodb.com/presentations/schema-design-scale-1

Page 30: 月間10億pvを支えるmongo db

3000万~1億PV

書込みは

一度だけ

Page 31: 月間10億pvを支えるmongo db

-> にバッファする-> Bulk Inserts/Operationsを使う

書き込みの回数を減らす

Page 32: 月間10億pvを支えるmongo db

-> にバッファする-> Bulk Inserts/Operationsを使う

書き込みの回数を減らす

From 2.6.0

Page 33: 月間10億pvを支えるmongo db

にバッファする

Page 34: 月間10億pvを支えるmongo db

-> オンメモリ型のKVS-> データ型が豊富 -> リスト・セット・ハッシュ

-> の苦手分野を補う

Page 35: 月間10億pvを支えるmongo db

-> は肥大化するデータの Updateは遅い-> はオンメモリ型のため リストの操作が早い

の苦手分野

Page 36: 月間10億pvを支えるmongo db

without

db.col.update({_id: 1}, {$push: {data: {x: 151, y: 100, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 179, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 266, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 295, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 322, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 333, ...}});db.col.update({_id: 1}, {$push: {data: {x: 151, y: 340, ...}});...

Page 37: 月間10億pvを支えるmongo db

db.col.insert({data: [ {x: 151, y: 100, ...}, {x: 151, y: 179, ...}, {x: 151, y: 266, ...}, {x: 151, y: 295, ...}, {x: 151, y: 322, ...}, {x: 151, y: 333, ...}, {x: 151, y: 340, ...}, ...]});

with

Page 38: 月間10億pvを支えるmongo db

Bulk Inserts/Operationsを使うFrom 2.6.0

Page 39: 月間10億pvを支えるmongo db

db.col.insert([ {first: “Yuji”, last: “Isobe”, city: “Osaka”}, {first: “Yuji”, last: “Isobe”, city: “Tokyo”}]);

使い方

var bulk = db.col.intializeOrderedBulkOp()bulk.find({first: “Yuji”}) .updateOne({$set: {city: “Tokyo”}});

Bulk Inserts

Bulk Operations From 2.6.0

Page 40: 月間10億pvを支えるmongo db

MongoDBは開発スピードが早く、パフォーマンス向上機能が次々と出るので、積極的に使いましょう

豆知識

Page 41: 月間10億pvを支えるmongo db

1億~3億PV

mongodmongodmongodmongodmongodmongodmongodmongodmongodmongod

Page 42: 月間10億pvを支えるmongo db

-> 用途ごとにDBを分ける-> Hotデータ/Coldデータを分ける-> 古くなったデータを削除する

DB設計

Page 43: 月間10億pvを支えるmongo db

-> Reader-Writerロックが使われている-> 2.2.0以降はDB単位でロックする-> マシンを分ければメモリが増える

なぜDBを分けるのか?

Page 44: 月間10億pvを支えるmongo db

-> メインデータ(Hot)-> メインデータ(Cold)-> 生データ-> 統計データ-> サイトデータ

におけるDBの用途

Page 45: 月間10億pvを支えるmongo db

-> Hotデータのロックを避ける-> Hotデータ用に大容量メモリ-> Coldデータ用に大容量ストレージ

Hotデータ/Coldデータを分ける

Page 46: 月間10億pvを支えるmongo db

-> S3にバックアップ-> 統計データを保存-> 定期的な自動削除

古いデータを削除する

Page 47: 月間10億pvを支えるmongo db

クエリの条件をタイプミスしてインデックスを使うことができず

MongoDB死亡…

スキーマレスあるある

Page 48: 月間10億pvを支えるmongo db

3億~10億PV

メモリが

欲しいです

Page 49: 月間10億pvを支えるmongo db

-> メモリは積めば積む程早くなる-> ディスクアクセスも早い方が良い -> SSDを使いましょう

チューニング

Page 50: 月間10億pvを支えるmongo db

EC2インスタンスの選び方

http://blog.mongodirector.com/mongodb-on-aws-how-to-choose-the-right-ec2-instance-type-for-your-mongodb-server/

Page 51: 月間10億pvを支えるmongo db

一般的な目的(m3)-> 最初に選ぶインスタンス

メモリの最適化(r3)-> メモリとCPUのバランスが良い

ストレージの最適化(i2/hs)-> SSDを使用。高負荷に耐えられる

EC2インスタンスの選び方

Page 52: 月間10億pvを支えるmongo db

r3.2xlarge-> vCPU: 8-> Memory: 61GiB-> SSD: 160GB-> Cost: $0.840 per Hour

i2.2xlarge-> vCPU: 8-> Memory: 61GiB-> SSD: 800GB x 2-> Cost: $2.001 per Hour

主に使用しているインスタンス

Page 53: 月間10億pvを支えるmongo db

継続的な監視

監視を止めたら

そこで異常終了

ですよ?

Page 54: 月間10億pvを支えるmongo db
Page 55: 月間10億pvを支えるmongo db

-> ホスティングサービスの ダッシュボード-> 毎日の健康チェック用-> 過去の情報は参照できない-> メリット・デメリットは下記参照ホスティングサービスで始めるMongoDBhttp://www.slideshare.net/yujiosaka/starting-mongo-db-on-hosting-services

Page 56: 月間10億pvを支えるmongo db
Page 57: 月間10億pvを支えるmongo db

-> 定期的な健康診断用-> リアルタイム監視はMongoHQ 過去の状態チェックはMMS-> アラートとバックアップもあり-> 導入が簡単なので、 とりあえず入れておくべき

Page 58: 月間10億pvを支えるmongo db

-> explain(true)-> system.profile.find()-> MongoDB professor-> Dex-> MongoHQ Slow Queries

遅いクエリの監視

Page 59: 月間10億pvを支えるmongo db

ObjectIdを使ったクエリの実行に100ms以上かかったら危険信号です

豆知識

Page 60: 月間10億pvを支えるmongo db

-> インデックスの仕組みを理解する-> 書き込みの回数を減らす-> DBを用途別に分ける-> メモリを増やす-> 継続的に監視する

my.presenation.aggregate()

Page 61: 月間10億pvを支えるmongo db

my.presentation.end “thank you ;)”

Page 62: 月間10億pvを支えるmongo db

any?.questions?