Upload
crooz-inc
View
7.614
Download
6
Embed Size (px)
Citation preview
を知ろう概要から動作原理まで
© CROOZ,Inc 1
アジェンダ
• mongoDBとは
• クラスタ構成概要
• 内部的動作原理
• その他の仕様と機能
• MySQLとのスピード比較
© CROOZ,Inc 2
mongoDBとは特徴から説く
© CROOZ,Inc 3
mongoDB
オンメモリで動作するスキーマフリーなドキュメンド指向NOSQLデータベース。
© CROOZ,Inc 4
mongoDBの背景
• 2009年よりMongoDB社(元 10gen)が提供。
• 累計調達資金 2億 3100万ドル。
• mongoDBのダウンロード数は 500万回に達する。
• mongoDB技術者の求人数は redisや Cassandraを抜いてトップを君臨。
• キーワードの検索数は HTML5に次ぐ 2番目に多い。
© CROOZ,Inc 5
※一部情報は TechCrunchから引用
MongoDBの特徴
• ドキュメンド指向– レコードではなく、 JSONオブジェクトが格納される。
• スキーマフリー– 動的なスキーマ、リレーションの概念なし。
• Memory-Mapped File– メモリ上で動作する前提の設計で高いパフォーマンスを叩き出す。
• レプリケーション、シャーディング構成– クラスタ構成により、自動的なフェイルオーバー、シャーディングを実現。
© CROOZ,Inc 6
ドキュメンド指向①
RDB mongoDB
Database (データベース ) Database (データベース )
Table (テーブル ) Collection (コレクション )
© CROOZ,Inc 7
KVSではなく DB!
テーブルレベルまで、基本的な構造は RDBを踏襲。
ドキュメンド指向②
Profile collection:{ name: “Alice”, age: 20, hobby: { “outdoor”: [ “motorcycle”, … ], “indoor”: [ “reading”, ], }}
© CROOZ,Inc 8
レコードの代わりに、 JSONライクなオブジェクトが格納される。
オブジェクトの構造は理解され、検索や参照に利用できる。
この例でアウトドアの趣味にアクセスするときは、 hobby.outdoorでアクセスできる。
こうしたサブオブジェクトやデータに対しインデックスの作成など、 DBの機能がフルで利用できる。
NOTE: 内部的には JSONが BSONという JSONのバイナリ版が格納され、 パフォーマンスの向上と容量削減に貢献している。
スキーマフリー①
• 動的なスキーマデザイン– レコードのようにテーブルごとにカラムが決まることはない。– 同じコレクションにあるドキュメンドの構造が違ってでも可。– 更新ごとにドキュメンドの構造を変更できる。– create系 APIが存在しない。
• リレーションの概念なし– 集約出来る情報は関連テーブルに分散するのではなく、同じドキュメンドのサブドキュメンドとして集約する。
– どうしても分割管理したい場合 (例:マスター )は DBRefというドキュメンド間のハイパーリンクを利用する。
© CROOZ,Inc 9
スキーマフリー②
books
book_id
book_title
© CROOZ,Inc 10
RDBでのタグシステムの実装例
book_tag_map
tag_id
book_id
book_tags
tag_id
tag_text
• bookと tagに関連する操作は 3つのテーブルを舐める必要がある。• ランダムアクセスは最低でも3回発生する。
スキーマフリー③
© CROOZ,Inc 11
MongoDBでのタグシステムの実装例
• tagsは bookのドキュメンドの一要素として格納。• tags配列に対してインデックスを作成し、検索に利用できる。• book自身の tagを参照する場合検索は必要ない。• 同一ドキュメンドのためディスク上では連続なので、ランダムアクセスは1回。
Books collection:{ _id: 1, title: “MongoDB”, tags: [“10gen”, “database”, “open-source”], …}
Memory-Mapped File
• Mongoではディスク上のリソースをMemory-Mapped Fileの仕組みを利用して、メモリ上にマッピングする。
• クライアントは通常メモリ上のデータを操作する。
• Memcacheなどのメモリキャッシュシステムの機能を原理的に併せ持つ。
© CROOZ,Inc 12
NOTE:詳細は後述
Table
MongoDBとは②
© CROOZ,Inc 13
上述の特徴を踏まえて、Mongoの運用思想とは。
Table
Table
ORマッピング
オブジェクト Memcache
RDBMSではデータの集約、整形を経て、プログラムが扱いやすい形にし上で、キャッシュシステムに格納しクライアントに提供する。
Mongoの設計思想でははじめからプログラムと親和性の高いオブジェクトをそのまま格納する。メモリ上で動作するという特徴上、キャッシュシステムも基本的には必要ない。
クラスタ構成レプリケーションとシャーディング
© CROOZ,Inc 14
クラスタ構成
• Mongoではレプリケーション、シャーディングの機能をそれぞれ提供している。
• レプリケーション構成において、一般的な条件下では障害からの自動フェイルオーバーが可能。
• シャーディング構成において、自動バランシング機能を備え、動的にノードの追加や除去に対応。
• 両者を組み合わせることで負荷分散された冗長構成のクラスタが出来上がる。
• クライアントからはクラスタ全体を一つの論理 DBにみなすことができる。
© CROOZ,Inc 15
クラスタ構成図
© CROOZ,Inc 16
セカンダリサーバー (Secondary)
仲裁サーバー (Arbiter)
メタデータ―サーバー (Config)
ルーティングサーバー (Mongos)
Config Servers
Mongos Server
Replica Set
Replica Set
Data Servers
プライマリサーバー (Primary)
クラスタ構成要素
• primaryサーバ―– アクセスを一手に受けて、セカンダリに同期していく。– フェイルオーバー時はセカンダリサーバーの中から投票によって選ばれる。
• secondaryサーバ―– デフォルトではデータに対して参照を含めアクセス不可。– フェイルオーバー時は投票によって最も同期が進んでると判断すれば、プライマリになる。
• arbiterサーバー– データを保持しないので同期もしないが、レプリカセット全体の同期状況を追跡していく。– 障害時に保持している同期状況で投票するために存在する。
• configサーバー– シャーディング構成の構成情報やシャード状況を保持する。– 構成が変更された時に、情報の提供と周知を担当する。
• mongosサーバー– クライアントにとっての窓口で、シャーディング構成のルーターのようなサーバー。– 接続時に configサーバーにシャーディング構成を問い合わせてキャッシュし、– この情報を手掛かりにデータをルーティングしていく。– Mongosサーバーはバックエンドを持たないただのプロセス。
© CROOZ,Inc 17
レプリケーションと自動フェイルオーバー
© CROOZ,Inc 18
primary secondary secondary
同期
同期
• 一つのレプリケーション構成はレプリカセットと呼ぶ。• レプリカセットは一つの primaryと複数の secondaryで構成される。• クライアントが操作できるのは primaryのみで、 primaryから oplogというオペレーションログで secondaryに同期していく。
primary secondary
同期障害
primary
• primaryが障害の場合、 secondaryの中から投票で新しい primaryが選ばれる。• 障害発生した primaryが復帰後は secondaryとして新 primaryから同期を受ける。• oplog内にスタックされたオペレーションで最新まで同期できない場合、自動フェイルオーバーは失敗となって、手動フォローが必要になる。
Primary 選挙と過半数票
© CROOZ,Inc 19
レプリカセットの primaryが障害した場合、レプリカセット内の残りの構成要素がそれぞれ同期が進んでいると判断した secondaryに投票する。障害要素を含む全構成要素の過半数票を獲得した secondaryが晴れて新しい primaryになる。
secondary
同期
primary
上記 primary、 secondary 各1の構成では、 primary 障害後残りの secondaryが自分自身の1票しかもらえず、1票より多い票数 ( 過半数票 )を獲得できず、 primary 選抜が失敗し自動フェイルオーバーも失敗となる。複数の secondaryを用意し対処しても、障害サーバーの数が合計数の半分になった時点で、同様に残りのサーバーが過半数票を獲得できない。
primary secondary arbiter
同期監視
この現象を解決するのが arbiterサーバー。レプリカセット内の同期状況を監視し、障害時は投票するだけの人。原理的に負荷やトラフィックが小さい。
優先読み込み( ReadPreference)
レプリカセットに対して参照リクエスト投げるとき、参照先をある程度指定することができる。
• プライマリ– すべての読み込みはプライマリに対して行う。( default)
• プライマリ優先– プライマリが接続不可などの状況でのみセカンダリを選択する。
• セカンダリ– 全セカンダリ中 ping 返答が 15ms 秒以内のメンバーからランダムに選択する。
• セカンダリ優先– 「セカンダリ」で使えるメンバーがなかった場合にのみプライマリを選択する。
• 最も近い– Ping 返答が一番近いメンバーを選択。メンバーの種類は気にしない。
• タグセット絞込み– 上記中「プライマリ」以外、タグセットで候補の選択範囲を絞る事ができる。
© CROOZ,Inc 20
レプリケーションまとめ
• Primary, Secondary, Arbiterサーバーで構成する。
• データサーバーの数に応じて Arbiterを用意し無駄をなす。
• 障害時は自動的にシステムの可動性を維持する。
• システム動作状態での復旧が可能。
• レプリカセットに対する読み込み先は細かく制御できる。
© CROOZ,Inc 21
シャーディングの概要
• シャードは全自動で行われる。シャードアルゴリズムの変更やカスタマイズは不可。
• システム動作状態でのシャード構成の変更が可能。
• 基本的にアプリケーションレベルでシャードを意識する必要がない。
© CROOZ,Inc 22
シャーディングの仕組み
© CROOZ,Inc 23
mongos
Primary shard Shard Shard
chunk0
0 ~ 100
chunk1
101 ~ 200
chunk2
201 ~ 301
{key: 150}
• データはドキュメンド単位ではなく、 chunkというデータの箱単位でシャードされる。
• インデックス作成と同じ要領でコレクション別のシャードキーを作成。このキーは変更不可。
• シャードキーに対しては RangeBasedPaginationのアルゴリズムでchunkに分割し、この chunkを各シャードに分散する。
• 振り分けられないデータは全部プライマリシャードサーバーでに行く。• プライマリシャードはコレクション別でシステムが勝手に割り振る。
chunk3
301 ~
Chunckの分割と移動
© CROOZ,Inc 24
mongos
Primary shard Shard Shard
chunk0
0 ~ 100 chunk1
101 ~ 200
chunk2
201 ~ 301chunk
3301 ~ 400
chunk4
401 ~ 500chunk
5501 ~
• 大きくなりすぎた chunkは分割される。• Chunkが特定のサーバーに偏った場合は移動される。• Chunkの移動と分割はパフォーマンスに与えるインパクトは大きい。• Chunkの移動や分割中には一部リクエストは正しい情報を返せなくなる。( count 等)
シャーディングの偏り対策
• ランダム性のあるデータをシャードキーにする。
• 複合キーをシャードキーにする。
• Chunkを事前に分割しておく。
• Chunkのサイズを小さく設定する。
• 定期的に手動で chunkを作成、分割してやる。
• Hashベースのシャードキーを利用する。
© CROOZ,Inc 25
Hashベースシャードキー
シャーディングのために作られた特殊なインデックス。
• 利点:– シャードのアルゴリズムにあわせているので、非常にうまい具合に分散される。
– 自動で事前 chunk分割してくれる。
• 欠点:– 複合キーは利用不可。ピンポイント検索では不利。
© CROOZ,Inc 26
シャーディング構成要素の障害時の挙動
• configサーバー障害– 一部障害の場合
• configサーバーのメタデータが読み取り専用になる。• DBに対する通常操作、mongosの立ち上げができるが、シャーディング構成の変更や Chunkの移動や分割ができなくなる。
• データの大量インサードがあった場合、偏ったシャーディング結果になるか、インサード失敗になる。
– 全部障害の場合• 一部障害の挙動に加え、mongosの追加や再起動ができなくなる。(精確には立ち上げ後落ちる)
• 一部シャーディング構成状態を確認するコマンドが利用できなくなる。
• Mongosサーバー障害– 単一mongosの障害はシステム自体にインパクトを与えない。– クライアントにとってはシングルポイントになるため、プロセスの自動再起動や、接続先切り替えの仕組みで回避できる。
© CROOZ,Inc 27
シャーディングのまとめ
• 全自動なため、アプリケーションで面倒を見る必要がない。
• シャード構成にのみ存在する問題や仕様がいろいろあるので、ある程度意識してリクエストを投げる必要がある。
• 適切なシャードキーの選択が肝、慣れるまでチューニングで苦労する可能性大。
© CROOZ,Inc 28
クラスタの物理構成例
• Primary, Secondaryサーバー– 高負荷、高ディスク IO、高トラフィック。– 実運用レベルではすべて物理サーバーが無難。
• Arbiterサーバー– 低負荷、低ディスク IO、低トラフィック。– データサーバーと分けていれば相乗り可。
• Configサーバー– 低負荷、低ディスク IO、低トラフィック。 – config同士が分けていれば相乗り可だが。
• Mongosサーバー– 低負荷?、ディスク IOなし、高トラフィック。 – トラフィックが気にしなければどこでもいい。
© CROOZ,Inc 29
とりあえず、クラスタ構成要素の特徴をまとめよう。
クラスタ内でケチる構成
© CROOZ,Inc 30
Shard1 Shard1
Shard2Shard2
• メインのデータサーバーはそれぞれ物理サーバーを用意。• 残り負荷の低いサーバーは一プロセスごとまとめて物理サーバーを用意。• Arbiterサーバーは複数プロセス相乗りでも可。• あまり勧めないが、 Configをデータサーバーに相乗りさせても可。• 基本的に Arbiter, Config, Mongosが一プロセスずつ同時に止まっても、システムに直ちに影響を与えない。
Config3Mongos
Arbiter1
Config2
Arbiter2
Mongos
Config1
AppServer
Mongos
AppServer
Mongos
クラスタ外でケチる構成
© CROOZ,Inc 31
Shard1 Shard1
Shard2 Shard2
• mongosは Appサーバーに置いて、 localhostから接続する。• その他の低負荷サーバーは一プロセスずつ適当なサーバーに相乗りさせる。• Appサーバーに余裕が有る場合、mongos 以外の低負荷プロセスに相乗りさせても可。
AppServer
SomeServer
Config1
Arbiter1
SomeServer
Config2
Arbiter2
AppServer
Mongos
Mongos
Config1
内部的な動作原理mmap()を利用した実装とジャーナリング
© CROOZ,Inc 32
内部的動作原理
© CROOZ,Inc 33
Mongoのコアはmmap()で実装している。
ディスク
メモリ
マッピング
• Mongoプロセス起動時にディスクにあるリソースを全部仮想メモリにマッピングする。
• マッピング時点ではデータはメモリに乗らない。• 一旦マッピングすると OSの機能でメモリとディスクが関連付けられて、メモリへの更新は任意のタイミングでディスクにフラッシュできる。
• Mongoではデフォルトで 60 秒ごとディスクにフラッシュする。
60 秒ごとの更新
Memory-Mapped Fileから見るMongoの特性
• 利点:– 通常はメモリ上で動作するため、動作が早い。 (特に書き込み )
– よく利用するデータは自然と物理メモリに来るので、メモリキャッシュシステムのような役割もこなす。
– 大量な書き込みでも相対的にディスク IOが小さい。• 欠点:
– 32bitシステムでは使いものにならない。– 仮想メモリ扱いなので、ページアウトが発生する。 (page
fault)– Mongoがアクティブに動く環境では他のプロセスをガンガンスワップアウトさせてしまう。
– 永続化は 60 秒ごとの更新なので、最悪 60 秒のデータが飛ぶ。
• 結論:– メモリをいっぱい積みましょう!© CROOZ,Inc 34
ジャーナリングシステム概要
• 単一プロセスの対障害能力を向上する目的で作られたシステム。
• 先行書き込みログの仕組みでパフォーマンスを維持しながら実現。
© CROOZ,Inc 35
消える 60 秒間のデータのために!
ディスク メモリ
ジャーナリングシステムの動作原理①
© CROOZ,Inc 36
DB Data Shared View
60sごとの更新
Write OP
Private View
Journaling File
100msごとの書き込み
• DBのデータは SharedViewというビューにマッピングされた後、 SharedViewを PrivateViewに第二のマッピングを行う。
• リクエストに対しライトオペレーションは SharedViewではなくPrivateViewに送られ、書き込み終了後 SharedViewに反映する。
• 100msごとに PrivateViewに送られたライトオペレーションだけをディスクのジャーナリングファイルに書き込む。
map
Memory-Mapped File
ディスク メモリ
Memory-Mapped File
ジャーナリングシステムの動作原理②
© CROOZ,Inc 37
DB Data Shared View
Private View
Journaling File
WriteOPを
再生
データをフラッシュ
• 障害復帰後、 JournalingFileから SharedView 宛にライトオペレーションを再生し、メモリ上のデータを復旧させる。
• SharedViewからディスクに最新データをフラッシュする。• SharedViewから PrivateViewに最新データをにリマップする。• これで復旧完了、リクエストを受け付ける。
remap
クラスタ構成でのジャーナリング
Mongoではレプリケーション構成でもジャーナリングの利用を推奨している。理由は以下:
• レプリケーション全体の障害に対応できる。
• より素早く確実なリカバリが出来る。
• 障害後はmongoプロセスを単純に再起動することで対応できる。
© CROOZ,Inc 38
ジャーナリングシステムのまとめ
• 利点:– 障害耐性向上。最大 60sのデータロスが 100msにできる。– レプリケーション構成での自動フェイルオーバー能力向上。– 永続性保証書き込みの敷居が下がる。 (詳細後述 )
• 欠点:– 同じビューがメモリ上2つ存在するため、メモリ消費量が倍!– 一回の更新で 2回のメモリ操作が発生する。– ジャーナリングファイル書き込み分のディスク IOが発生する。
• 結論:– 特別な理由がなければ利用した方がいい。
© CROOZ,Inc 39
その他の仕様と機能特徴的な仕様とその他の機能を紹介
© CROOZ,Inc 40
特徴的な仕様①: Fire-and-Forgetの精神
• 書き込みリクエストに対し、mongoは実際のディスク書き込みを確認しない。
• この仕様でメモリ動作の優位性を保ち高いパフォーマンスを維持する。
• ディスク書き込みを保証してほしい場合、多くのドライバは fsyncパラメータをサポートする。
© CROOZ,Inc 41
特徴的な仕様②: fsync
• Mongoでは fsyncは管理コマンド。メモリをディスクに直ちにフラッシュさせる。
• 各言語のドライバでは書き込み系 APIのオプション。– 指定すると該当オペレーションのディスク書き込みを保証する。– ただし、ジャーナリングありとなしで挙動が違う。– ジャーナリングなし:
• メモリへの書き込み後、直ちにディスク書き込みが行われる– ジャーナリングあり:
• メモリへの書き込み後、ジャーナリングファイル書き出しの最大100ms間隔を待つ。
– ジャーナリングありではより低負荷で永続保証書き込みできる。– でも、用法用量を守って正しく使うべき。
© CROOZ,Inc 42
特徴的な仕様②: 書き込み確認(WriteConcern)
• Fire-And-Forgetの精神をより細かくコントロールするための機能が書き込み確認。
• リクエストに対しどの段階まで成功とみなすかを表すリクエストのオプション。
• 主な確認レベル:– {w:-1} 完全に確認なし。– {w: 0} インフラレベルのエラー(ネットワークやMongoの死活など)のみ
確認。– {w: 1} SharedView への書き込みを確認。不正データなどが検出できる。
(default)– {w:$n} ($n>1) レプリカセット内で $n 個のノードへの書き込みを確認。– {w:$tags} $tagsで指定した特定のレプリカセットへの書き込みを確認。
© CROOZ,Inc 43
送り出したリクエストが心配で心配で仕方ない方に
その他の機能
• MapReduce– ビッグ・データの解析機能をデフォルトで搭載。
• 固定長コレクション( Capped)– サイズやドキュメンド数が予め決まった特殊なコレクション。– 挿入に対して非常に高いパフォーマンスを持つ。– シャードできない。
• 二次元地理空間インデックス– 2D 座標インデックスによる距離的な検索ができる。– 平面モデルと球面モデルをサポート。– このインデックスはシャードキーに指定できない。
© CROOZ,Inc 44
MYSQLとのスピード比較参考程度に
© CROOZ,Inc 45
MySQLとのスピード比較
• マシーンはその辺にあるノート PC。
• MySQLはデフォルト状態。MongoDBはシャード構成上にシャードしな
いコレクションを作成し利用。
• 両方 PHPドライバを利用。
• 比較用の値は平均値。
• 書き込み系でメモリベースは 20万回計測、ディスクベースは 1万回計測。
• Selectは 20万件中ランダム 1 件を 1万回計測。
• 適当なベンチなため、参考程度。
© CROOZ,Inc 46
パフォーマンスのスケール感をつかむために、簡単にMySQLとベンチを取ってみた。
MySQLとのスピード比較
Insert Update Select(key)
Select Delete
MongoDB 0.00024 0.00044 0.00014 0.03283 0.00068
MySQL 0.03839 0.04059 0.00009 0.03236 0.04127
© CROOZ,Inc 47
• 書き込み系のスピードが圧倒的であることがわかる。
• Selectではインデックスなしは同じ程度、インデックスありは遅
い結果となり、おそらく搭載メモリ量の影響でしょう。
書き込み確認別の比較
© CROOZ,Inc 48
w:1 fsync
Journaling 0.00024 0.04499
noJournaling 0.00020 0.10565
• デフォルト設定でもジャーナリングがもたらすパフォーマンス低
下が思ったより小さい。
• ジャーナルあり状態の fsyncは仕組み上比較的に早い。
まとめ導入側の観点から
© CROOZ,Inc 49
管理者の観点から
• クラスタ構成の完成度が高いため、大きなシステムでも相対的に構築、運営しやすい。
• 真新しいシステムなので、当然相応の導入コストがかかる。
• シャーディング関連のノウハウが蓄積されるまで苦労する可能性大。
© CROOZ,Inc 50
開発者の観点から
• 早い。
• レプリケーションとシャーディングはアプリレベルで面倒を見る必要がない。
• データが取り回しやすくなり、実装が単純になる。
• スキーマの設計思想がまるっきり違うので、発想の転換が必要。
• シャーディングでは実装レベルで注意すべきことが多い。
© CROOZ,Inc 51
使ってみましょう!
© CROOZ,Inc 52