MongoDB
MongoDB はドキュメントデータベースです。
The most popular database for modern apps | MongoDB
ドキュメントデータベースは、JSON のような形式でデータを保存するデータベースです。
感覚的には、キーバリューストアのバリュー部分に JSON を利用できるデータベースです。
MongoDB では、JSON を拡張した BSON(Binary JSON)を利用しています。
データ形式の変更が多いゲームアプリケーションや、様々なデータ形式で出力されるログなどの格納先として利用されます。
余談ですが、MongoDB のドキュメントは様々な情報が丁寧に記載されており、読みやすくかつ非常に読み応えがあります。
The MongoDB 4.4 Manual — MongoDB Manual
RDBMS とよく比較される NoSQL です。
お気持ちとしては、データベースのスキーマをデータベースで決めるのが RDBMS で、ドキュメントストアはアプリケーションで設計します。
どっちが大変かくらいの差のような気がしてます。
基本的には、RDBMS を使うのが良さそうな気がしています。
システムが超大規模になるとか、ユースケースにめっちゃ合ってるとかなら、MongoDB を利用するのもありみたいです。
system-design-primer/README-ja.md at master · donnemartin/system-design-primer · GitHub
というか、大規模な場合だとシャーディング構成になるけど、シャーディングのバックアップ/リストアって有料版の機能なんですよね。
つまり、そういうこと。
MongoDB の特徴
前述のように、ドキュメントストアであることが大きな特徴です。
ドキュメントストアですと、Apache CouchDB もありますが、こちらは MongoDB よりもシンプルなものになっています。
MongoDB は何でもできるデータベースという感じです。
アーキテクチャー
BSON をドキュメントと呼び、ドキュメントの集まりをコレクションといいます。
コレクションは、RDB のテーブルに対応するものです。
コレクションの集まりをデータベースと呼びます。
MongoDB にドキュメントを格納すると、実際には以下のようになります。
var mydoc = { _id: ObjectId("5099803df3f4948bd2f98391"), name: { first: "Alan", last: "Turing" }, birth: new Date('Jun 23, 1912'), death: new Date('Jun 07, 1954'), contribs: [ "Turing machine", "Turing test", "Turingery" ], views : NumberLong(1250000) }
_id は、ObjectId と呼ばれ、ドキュメントを一意に特定するもので、RDB での主キーに対応するものになります。
その他、利用できる型は以下にまとめられています。
BSON Types — MongoDB Manual
インデックス
RDB と同様にインデックスを張ることができます。
デフォルトでは、_id がインデックスと利用されますが、ランダムな値であるため高速化に寄与しません。
高速化をおこなうために、特定のフィールドに対してインデックスを張ることができます。
このインデックスは必ずしもすべてのドキュメントに対応させる必要はなく、特定のフィールドを持つものだけを対象としてインデックスを張れます。
Change Stream
コレクションを監視して、更新処理を時系列データとして利用できます。
例えば、変更を検知した場合に、Apache Kafka などのメッセージングキューにデータを送信する、などの処理ができます。
レプリカセット
レプリケーションにより冗長化できます。MongoDB ではプライマリーとセカンダリーからなるレプリケーションクラスターをレプリカセットと呼びます。
一般的なレプリケーションと同様に、プライマリーのデータをセカンダリーに同期します。
レプリケーションは、oplog (operation log)と呼ばれる、実行コマンドを記録したログを用いて行われます。
また、レプリケーションは非同期レプリケーションです。
各ノード同士は、ハートビートにより生存確認を行っており、プライマリーに障害が発生した場合にはセカンダリーをマスターに昇格させます。
このとき、クォーラムを行うために3台以上のノードが必要となります。
しかし、コストなどの理由により高性能なサーバーを2台しか用意できない場合、データをもたない Arbiter というノードを利用できます。
Arbiter はデータを持たず、クォーラムによるマスターの選出にのみ参加します。
話をセカンダリーに戻すと、セカンダリーサーバーは複数の種類があります。
主に以下のものがあります。
種類 | マスターに昇格する | アプリケーションからの参照 | マスターデータとの違い |
---|---|---|---|
通常 | ◯ | ◯ | 同じ |
Priority 0 Replica Set Member | ☓ | ◯ | 同じ |
Hidden Replica Set Member | ☓ | ☓ | 同じ |
Delayed Replica Set Member | ☓ | ☓ | 古い |
Hidden Replica Set Member は、Priority 0 Replica Set Member であり、Hidden Replica Set Member は、Delayed Replica Set Member です。
Priority 0 Replica Set Member は、広域災害などに備えてプライマリーや通常のセカンダリーから離れたデータセンターに配置します。
Hidden Replica Set Member は、管理者用のセカンダリーになります。通常のアプリケーションからのデータを処理していないため、データ分析などの用途に利用しやすいです。
Delayed Replica Set Member は、不足の事態によりデータが失われた場合に備えたものになります。
シャーディング
MongoDB は、ドキュメントストアであり、水平スケーリングに適しています。
サーバーの台数を増やすことで、参照・更新ともに負荷分散が実現可能です。
Shard、Config Server、mongos から構成されます。
- Shard:MongoDB インスタンスです。冗長性を確保するためにレプリカセットにすることが多いです。
- Config Server:クラスターを管理するサーバーであり、メタデータを保持しています。可用性を確保するためにレプリカセットにすることが多いです。
- mongos:アプリケーションサーバーに配置されるルーターです。リバースプロキシのような役割を担っており、Config Server から取得したメタデータを元に、データを Shard たちにルーティングします。
シャーディング方式としては、ハッシュ値を利用したハッシュシャーディングと値を範囲を利用したレンジシャーディングが利用できます。
シャーディングにおいて、データはチャンクと呼ばれる単位で管理されています。
最大64MBほどのデータとなっています。
MongoDB では、シャードごとのデータが均等になるようにチャンクを統合・分割したり、シャード間で移動させることで適切な状態を保ってくれます。
特に、チャンクの格納されるデータは上記のシャーディング方式に従ってまとめられています。
いい感じにデータが分散できるように、シャーディング方式を選択する必要があります。