今回は「MongoDB の シャーディング」についてまとめます。
スケーリング
いきなりシャーディングの話を始める前にそもそものスケーリングについて触れておきたいと思います。
一般的なスケーリングの話として、システム規模が大きくなるとスケーリング(拡張)が必要になってきます。 スケーリング方法は大きく2種類あり、具体的には「垂直スケーリング」と「水平スケーリング」があります。
- 垂直スケーリング
- CPUやRAM、ストレージをより高性能なものに取り換えていく方法です。 スケーリングは簡単ですが、そもそものCPUやメモリに限界があるのである程度で性能限界が来てしまいます。
- 水平スケーリング
- データセットでシステム分割を行い、複数サーバーから並列で読み取れるようにする方法です。 総合的な性能は垂直スケーリングするよりも良くなりますが、スケールすればするほど複雑さが増すため管理が難しくなります。
シャーディングとは
シャーディングとは「データを複数サーバーに分散展開させる仕組み」で、その特徴から「水平スケーリング」を実現する仕組みです。 …と言われてもいまいちピンとこないですが。。
シャーディングを行うことで大きく3つの利点(「読み書き処理が速くなる & 性能を上げやすい」「ストレージが増設しやすい」「可用性が上がる」)があります。 それぞれ詳しくは以下で見ていきますが、MongoDB では標準機能としてシャーディング(水平スケーリング)をサポートします。
読み書き
データをシャードクラスタに分散して保存しておくことで、読み書き処理(ファイルI/O)を分散して処理できるようになります。 ファイル読み書き(ファイルI/O)は遅い処理なので、これが分散化することでより高速な読み書きができるようになります。 また、読み書きの負荷が上がってきたとしてもサーバーを増やしていくことで水平スケーリングできます。
ストレージ
シャードクラスタには断片データを分散して保存します。 データ量が増えた際もサーバーを増やしていくことで水平スケーリングできます。
高可用性
シャードクラスタでは部分読み書きができます。 読み書きができなかった場合、操作ができるシャードサーバーから取得してくることもできます。
シャードクラスタ
MongoDB におけるシャーディングは以下の3コンポーネント(シャード、ルーター、設定サーバー)で成り立っています。 それぞれの関係性と説明は以下の通りです。
- シャード
- シャードサーバーにはコレクションを分割した断片データ(チャンク)を保存します。 シャードサーバーはレプリカセットで構成することができます。
- ルーター
mongos
はクエリルーターとしてアプリケーションからシャードクラスタへのインターフェースを提供します。 シャードクラスタへアクセスする際は必ずmongos
経由でアクセスします。 シャード化していないコレクションだったとしても必ずmongos
経由でアクセスします。- 設定サーバー
- シャードクラスタ設定に関するメタデータを保存します。 どのシャードサーバーにデータがあるかなどもこのサーバーに保存されます。 MongoDB 3.4 以降では設定サーバーを レプリカセット で構成します。
シャードキー
「シャードキー」はデータを分散してシャードサーバーへ保存する際にキーとして利用する情報のことを言います。 MongoDB は「シャードキー」を用いてコレクション内ドキュメント分散化を行います。
以下の図は x
をシャードキーとして分散化している簡単な例になります。
「シャードキー」についておさえておきたいポイントは以下の3点です。
- すべてのドキュメントに存在する不変なフィールドまたはフィールド群で構成します。
- 一度シャードキーを決めて分散化を行ってしまうと、再度シャードキーを変更することはできません。
- シャーディングするコレクションはシャードキーを含むインデックスが必要です。
もちろんシャードキーの選択によって性能、効率、拡張性に大きな影響が出るのは言うまでもありません。 シャードキーの選択が不適切であれば、前述の通りシャードサーバーに偏りが発生して非効率な動作となることもあり得ます。
チャンク
前述の通り、MongoDBは「シャードキー」の値でデータ保存の分散化を行いますが、このとき「チャンク」と呼ばれる塊ごとにグルーピングしてシャードサーバーへ分散保存します。 MongoDB はこの「チャンク」がシャードクラスタ内でバランスよく分散化されるよう、自動的に移動を行います。
チャンクへ分割およびそれを各シャードへ分散保存するイメージは以下のような図になります。
シャードデータに対する操作の制約
シャーディングしたデータ(シャードデータ)に対する操作にはいくつか制約があります。 その具体的なものを以下にとりあげます。
- groupコマンドが使えない。
代わりに aggregate ないし MapReduce を利用します。 - updateOne や deleteOne など単一ドキュメント操作の場合は シャードキー か
_id
の指定が必要です。
シャードキー か_id
が含まれていない場合エラーになります。 - シャーディングしたコレクションにはユニークインデックスが必要。
シャードコレクションと非シャードコレクション
MongoDBではシャード化するコレクションとシャード化しないコレクションを混在させることができます。 シャード化するコレクションはシャードクラスタに分散して保存されますが、シャード化しないコレクションはプライマリシャードに保存されます。
データ分散方法
シャード化する際の分散方法は「ハッシュシャード」と「レンジシャード」の2通りがあります。
ハッシュシャード
シャードキーのハッシュ値を利用してデータ分散を行います。 ハッシュを利用したシャードの場合、シャードキーの値が近かったとしてもチャンクがバラバラになりやすい特徴があります。 つまり、シャードキーが単調変化するようなケースで分散化させやすい分散化方法です。 逆にデータが分散化しやすいため、データ構造や取得方法によってはブロードキャスト操作が増える懸念もあります。
レンジシャード
シャードキーのレンジによってデータ分散を行います。 ハッシュシャードと異なり、シャードキーの値が近ければ同じチャンク上に存在する可能性が高くなる分散化方法です。 シャードキーの選定が不適切であればせっかくシャードという分散化技術を利用しようとしているにもかかわらず特定サーバーに負荷が偏ってしまうような懸念があります。
今回は「MongoDB の シャーディング」についてまとめました。
参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!