Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
月間10億PVを
支えるMongoDB
speaker: Yuji Isobe
name: Yuji Isobe
attributes: [
engineer
consultant
security specialist
startup member 
of
]
-> 2年間で月間10億PVを支える
 まで成長した の
「泥臭い」負荷対策をお話します
-> あるある紹介
-> 今はまだ問題点を洗い出している段階
 ベストプラクティスがあれば教えて欲しい
goals:
月間10億pvを支えるmongo db
大量データ
大量データトラフィック急増
-> 合計月間PV10億
-> 秒間平均400PV
-> 平均同時接続数5万
-> 月間保存データ量10TB
db. .stats()
back_ends: [
Node.js
CoffeeScript
MongoDB
Redis
AWS
]
front_ends: [
Nginx
Ruby on Rails
MySQL
memcached
AWS
]
architecture:
back_ends: [
Node.js
CoffeeScript
MongoDB
Redis
AWS
]
front_ends: [
Nginx
Ruby on Rails
MySQL
memcached
AWS
]
architecture:
we.use( ).explain()
-> スキーマレス
-> 安定した書き込み
-> 柔軟なクエリ
-> 容易なスケールアウト
-> との相性の良さ
月間10億PVへの道のり
-> ∼3000万PV
-> 3000万∼1億PV
-> 1億∼3億PV
-> 3億∼10億PV
-> 継続的な監視
∼3000万PV
い
い
か
ら
イ
ン
デ
ッ
ク
ス
だ
!!!
-> メモリ上に乗れば高速
-> 1クエリにつき1インデックス
-> B-Treeのバランスが重要
インデックスを理解する
-> メモリ上に乗れば高速
-> 1クエリにつき1インデックス
-> B-Treeのバランスが重要
インデックスを理解する
From 2.6.0
メモリ上に乗れば高速
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
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
メモリ上に乗らなければ遅くなる
プログラムからフィールドを削除
したが、インデックスを消し忘れ、
無駄なインデックスが残る…
スキーマレスあるある
1クエリにつき1インデックス
From 2.6.0
db.users.ensureIndex({first:1});
db.users.ensureIndex({last:1});
db.users.ensureIndex({
first:1,
last:1
});
index
intersection
compound
index
vs.
-> 複数の検索条件を
 組み合わせたインデックス
-> 2つのインデックスを使った
 検索結果の共通部分を返す
{first: Yuji , last: Isobe , city: Osaka }
From 2.6.0
db.users.ensureIndex({first:1});
db.users.ensureIndex({last:1});
db.users.ensureIndex({
first:1,
last:1
});
index
intersection
compound
index
vs.
-> 複数の検索条件を
 組み合わせたインデックス
-> 2つのインデックスを使った
 検索結果の共通部分を返す
{first: Yuji , last: Isobe , city: Osaka }
From 2.6.0
このクエリを早くしたい
db.users.ensureIndex({first:1});
db.users.ensureIndex({last:1});
db.users.ensureIndex({
first:1,
last:1
});
index
intersection
compound
index
vs.
メリット
-> 同時にいくつでも
デメリット
-> 用途は限定的
メリット
-> 柔軟な用途
デメリット
-> 現在は同時に2つまで
2.6.0以降は
消してしまっても
いいかも知れません
From 2.6.0
B-Treeのバランスが重要
-> インデックスにB-Treeを採用
-> B-Treeは常に平衡を保っている
インデックスの構造
文字列のインデックス
-> Hotデータが分散
-> メモリ効率が悪い
ObjectId・時間のインデックス
-> Hotデータが集中
-> メモリ効率が良い
できるだけObjectIdを使いましょう
後からの変更は大変です(経験談)
教訓
Schema Design at Scale
http://www.mongodb.com/presentations/schema-design-scale-1
3000万∼1億PV
書
込
み
は
一
度
だ
け
-> にバッファする
-> Bulk Inserts/Operationsを使う
書き込みの回数を減らす
-> にバッファする
-> Bulk Inserts/Operationsを使う
書き込みの回数を減らす
From 2.6.0
にバッファする
-> オンメモリ型のKVS
-> データ型が豊富
 -> リスト・セット・ハッシュ
-> の苦手分野を補う
-> は肥大化するデータの
 Updateは遅い
-> はオンメモリ型のため
 リストの操作が早い
の苦手分野
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, ...}});
...
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
Bulk Inserts/Operationsを使う
From 2.6.0
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
MongoDBは開発スピードが早く、
パフォーマンス向上機能が次々と
出るので、積極的に使いましょう
豆知識
1億∼3億PV
mongod
mongod
mongod
mongod
mongod
mongod
mongod
mongod
mongod
mongod
-> 用途ごとにDBを分ける
-> Hotデータ/Coldデータを分ける
-> 古くなったデータを削除する
DB設計
-> Reader-Writerロックが使われている
-> 2.2.0以降はDB単位でロックする
-> マシンを分ければメモリが増える
なぜDBを分けるのか?
-> メインデータ(Hot)
-> メインデータ(Cold)
-> 生データ
-> 統計データ
-> サイトデータ
におけるDBの用途
-> Hotデータのロックを避ける
-> Hotデータ用に大容量メモリ
-> Coldデータ用に大容量ストレージ
Hotデータ/Coldデータを分ける
-> S3にバックアップ
-> 統計データを保存
-> 定期的な自動削除
古いデータを削除する
クエリの条件をタイプミスして
インデックスを使うことができず
MongoDB死亡…
スキーマレスあるある
3億∼10億PV
メ
モ
リ
が
欲
し
い
で
す
-> メモリは積めば積む程早くなる
-> ディスクアクセスも早い方が良い
 -> SSDを使いましょう
チューニング
EC2インスタンスの選び方
http://blog.mongodirector.com/mongodb-on-aws-how-to-choose-the-right-ec2-instance-type-for-your-mongodb-server/
一般的な目的(m3)
-> 最初に選ぶインスタンス
メモリの最適化(r3)
-> メモリとCPUのバランスが良い
ストレージの最適化(i2/hs)
-> SSDを使用。高負荷に耐えられる
EC2インスタンスの選び方
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
主に使用しているインスタンス
継続的な監視
監
視
を
止
め
た
ら
そ
こ
で
異
常
終
了
で
す
よ
?
月間10億pvを支えるmongo db
-> ホスティングサービスの
 ダッシュボード
-> 毎日の健康チェック用
-> 過去の情報は参照できない
-> メリット・デメリットは下記参照
ホスティングサービスで始めるMongoDB
http://www.slideshare.net/yujiosaka/starting-mongo-db-on-hosting-services
月間10億pvを支えるmongo db
-> 定期的な健康診断用
-> リアルタイム監視はMongoHQ
 過去の状態チェックはMMS
-> アラートとバックアップもあり
-> 導入が簡単なので、
 とりあえず入れておくべき
-> explain(true)
-> system.profile.find()
-> MongoDB professor
-> Dex
-> MongoHQ Slow Queries
遅いクエリの監視
ObjectIdを使ったクエリの実行に
100ms以上かかったら危険信号です
豆知識
-> インデックスの仕組みを理解する
-> 書き込みの回数を減らす
-> DBを用途別に分ける
-> メモリを増やす
-> 継続的に監視する
my.presenation.aggregate()
my.presentation
.end thank you ;)
any?.questions?

More Related Content

月間10億pvを支えるmongo db