シャーディングされたクラスター バランサー
MongoDB バランサーは、シャーディングされたコレクションごとに、各シャードのデータ量を監視するバックグラウンド プロセスです。 任意のシャード上のシャーディングされたコレクションのデータ量が特定の移行しきい値に達すると、バランサーはゾーンを尊重しながらシャード間でデータを自動的に移行し、シャードあたりのデータ量を均等にしようとします。 デフォルトでは、バランサー プロセスは常に有効になっています。
シャーディングされたクラスターのバランシング手順は、ユーザー層とアプリケーション層には完全に透過的ですが、処理中にパフォーマンスにいくらか影響が出る可能性があります。
バランサーは、コンフィギュレーションサーバー レプリカセット(CSRS)のプライマリ上で実行されます。
単一のコレクションのコレクション バランシングを構成するには、 configureCollectionBalancing
を参照してください。
シャーディングされたクラスターのバランサーを管理するには、「シャーディングされたクラスター バランサーの管理」を参照してください。
バランサー内部
範囲の移行には、帯域幅とワークロードの面でいくらかのオーバーヘッドが伴い、どちらもデータベースのパフォーマンスに影響を与える可能性があります。バランサーは次の方法で影響を最小限に抑えようとします。
シャードを一度に最大で 1 つの移行に制限します。具体的には、シャードは同時に複数のデータ移行に参加することはできません。バランサーは、範囲を一度に 1 つずつ移行します。
MongoDB は並列データ移行を実行できますが、シャードが一度に参加できる移行は最大 1 つだけです。n個のシャードを持つシャーディングされたクラスターの場合、MongoDB は最大n/2 (切り捨て) の同時移行を実行できます。
「非同期範囲移行クリーンアップ」も参照してください。
バランシング ラウンドは、シャーディングされたコレクションのデータが最も多いシャードと、そのコレクションのデータが最も少ないシャードとの間のデータ量の差が、移行しきい値に達した場合にのみ開始します。
メンテナンスのために一時的にバランサーを無効にすることはできますが、バランサーを長期間無効のままにするとクラスターのパフォーマンスが低下する可能性があります。 詳細については、「 バランサーを無効にする 」を参照してください。
また、バランサーの実行時間を制限して、本番環境のトラフィックに影響を与えないようにすることもできます。詳細については、「バランシング ウィンドウのスケジュール」を参照してください。
注意
バランシング ウィンドウの仕様は、コンフィギュレーションサーバー レプリカセットのプライマリのローカル タイム ゾーンを基準にしています。
クラスターからのシャードの追加と削除
クラスターにシャードを追加すると、新しいシャードにはデータがないため、不均衡が生じます。MongoDB は新しいシャードへのデータの移行をすぐに開始しますが、クラスターのバランスがとれるまでに時間がかかる場合があります。クラスターにシャードを追加する手順については、「クラスターへのシャードの追加」チュートリアルを参照してください。
Tip
アプリケーションが開始前 を満たしている場合は、 reshardCollection
コマンドを使用してクラスター全体にデータを再分散し、新しいシャードを含めることができます。 このプロセスは、代替の範囲移行手順 よりもはるかに高速です。
例については、「新しいシャードへのデータの再配布 」を参照してください。
クラスターからシャードを削除すると、そのシャードにあるデータをクラスター全体に再分配する必要があるため、同様の不均衡が生じます。MongoDBは削除されたシャードをすぐにドレインし始めますが、クラスターのバランスがとれるまでに時間がかかる場合があります。このプロセス中は、削除されたシャードに関連付けられているサーバーをシャットダウンしないでください。
チャンクの分布が不均一なクラスター内のシャードを削除すると、バランサーはまずドレイン シャードからチャンクを削除し、次に残りの不均一なチャンクの分布のバランスをとります。
クラスターからシャードを安全に削除する方法については、「クラスターからのシャードの削除」チュートリアルを参照してください。
範囲移行手順
すべての範囲の移行では、次の手順を使用します。
バランサーは
moveRange
コマンドをソース シャードに送信します。ソースは内部
moveRange
コマンドを受信すると移動を開始します。移行プロセス中、範囲に対する操作はソース シャードに送信されます。ソース シャードは、範囲に対して受信する書込み (write) 操作に責任を負います。宛先のシャードは、ソースに必要なインデックスのうち、宛先に存在しないインデックスを構築します。
宛先シャードは、範囲内のドキュメントのリクエストを開始し、データのコピーの受信を開始します。 「範囲の移行とレプリケーション 」も参照してください。
ターゲット シャードは、範囲内の最終ドキュメントを受け取った後、同期プロセスを開始して、移行中に発生した移行済みドキュメントへの変更が確実に反映されるようにします。
完全に同期されると、ソースシャードはコンフィギュレーションデータベースに接続し、その範囲の新しいロケーションでクラスター メタデータを更新します。
ソース シャードがメタデータの更新を完了し、範囲内で開いているカーソルがなくなると、ソース シャードはドキュメントのコピーを削除します。
注意
バランサーがソース シャードから追加のチャンク移行を実行する必要がある場合、バランサーは現在の移行プロセスがこの削除ステップを完了するのを待たずに、次のチャンク移行を開始することがあります。「非同期範囲移行クリーンアップ」を参照してください。
警告
移行を伴うシャーディングされたクラスターでのセカンダリからの読み取りにおいて、ドキュメントが失われる可能性
シャーディングされたクラスターでのセカンダリからの読み取りが長時間行われていると、移行が行われている場合、ドキュメントが失われる可能性があります。
チャンク移行中にチャンクを削除する前に、MongoDB は orphanCleanupDelaySecs
か、またはチャンクに関連する進行中のクエリがシャード プライマリで完了するまでかの、どちらか長い方で待機します。最初はプライマリだったノードで実行されたが、ノードがセカンダリにステップダウンした後も継続されるクエリは、最初にセカンダリで実行されたかのように扱われます。つまり、サーバーは、現在のプライマリ上のチャンクを対象とするクエリがない場合にのみ orphanDelayCleanupSecs
を待ちます。
チャンクをターゲットとし、セカンダリで実行されるクエリでは、クエリにかかる時間が orphanCleanupDelaySecs
を超えるとドキュメントが失われる可能性があります。
移行しきい値
クラスターへのバランシングの影響を最小限に抑えるため、バランサーは、シャーディングされたコレクションのデータ分布が一定のしきい値に達した後にのみ、バランシングを開始します。
コレクションは、その中のシャード間のデータの差が、コレクションに設定されている範囲サイズの 3 倍未満である場合、バランスがとれていると見なされます。デフォルトの範囲サイズが 128MB
の場合、移行を行うには、2 つのシャードで、特定のコレクションのデータ サイズに少なくとも 384MB
の差がなくてはなりません。
非同期範囲移行クリーンアップ
シャードからデータを移行するために、バランサーは一度に 1 つの範囲を移行します。ただし、バランサーは現在の移行の削除フェーズが完了するのを待たずに、次の範囲の移行を開始します。範囲移行プロセスと削除フェーズについては、「範囲の移行を参照してください。
このキューイング動作により、事前分割せずに初期データロードを実行したり、新しいシャードを追加したりする場合など、クラスターのバランスが大幅に崩れている場合に、シャードはより迅速にデータをアンロードできます。
この動作は moveRange
コマンドにも影響し、moveRange
コマンドを使用する移行スクリプトはより迅速に進行する可能性があります。
場合によっては、削除フェーズがさらに長く続くことがあります。削除フェーズ中にフェイルオーバーが発生した場合の回復力が高まるように、範囲の移行が強化されます。このフェーズ中にレプリカセットのプライマリがクラッシュしたり再起動したりしても、孤立したドキュメントはクリーンアップされます。
_waitForDelete
バランサー設定により動作が変更されると、現在の移行の削除フェーズは、次のチャンク移行の開始をブロックする可能性があります。この _waitForDelete
は、通常、内部テスト用です。詳細については、「 削除の待機」を参照してください。
注意
範囲の削除はリソース集中型の操作であり、クラスターがドキュメントを削除する際にはキャッシュと I/O 負荷が増大します。
クラスターにシャードを追加する場合や、シャーディングされたシャーディングされたコレクションを複数のシャードに初期分散する場合など、大量のデータを移動する予定の場合は、代わりにコレクションを再シャーディングすることを検討してください。リシャーディング操作には範囲クリーンアップが必要ないため、クラスターへの負荷がはるかに軽減されます。
詳細については、「 コレクションの再シャーディング 」を参照してください。
範囲の移行とレプリケーション
範囲の移行中、 _secondaryThrottle
値によって、範囲内の次のドキュメントへの移行が進むタイミングが決められます。
config.settings
コレクション内:
バランサーの
_secondaryThrottle
設定が書込み保証 (write concern)に設定されている場合、範囲の移行中に移動された各ドキュメントは、次のドキュメントに進む前に要求された確認応答を受ける必要があります。移行プロセスでは、
_secondaryThrottle
が未設定の場合、セカンダリへのレプリケーションを待たずに次のドキュメントに進みます。
バランサーの _secondaryThrottle
パラメーターを更新するには、「セカンダリ スロットル」を例として参照してください。
_secondaryThrottle
の設定とは別に、範囲移行の特定のフェーズには次のレプリケーションポリシーが適用されます。
MongoDB は、範囲の場所を使用してコンフィギュレーションサーバーを更新する前に、ソース シャード上の移行先のコレクションに対するすべてのアプリケーションの読み取りと書き込みを一時停止し、更新後にアプリケーションの読み取りと書き込みを再開します。範囲の移動では、コンフィギュレーションサーバーに範囲の移動をコミットする前後で、レプリカ セットのノードの過半数がすべての書き込みを確認する必要があります。
外向きの移行が終了してクリーンアップが行われたら、(他の外向きの移行による)クリーンアップまたは新しい内向きの移行を続行する前に、すべての書き込みを大多数のサーバーに複製する必要があります。
config.settings
コレクションの _secondaryThrottle
設定を更新する際の例については、「セカンダリ スロットル」をご覧ください。
移行する範囲あたりのドキュメントの最大数
デフォルトでは、範囲内のドキュメント数が、構成された範囲サイズを平均ドキュメントサイズで割った結果の 2 倍を超える場合、MongoDB は範囲を移動できません。MongoDB でチャンクのサブ範囲を移動して、サイズをその結果より小さくできる場合、バランサーは範囲を移行することで移動できます。db.collection.stats()
には、コレクション内の平均ドキュメント サイズを表す avgObjSize
のフィールドが含まれます。
移行するには大きすぎるチャンクの場合
バランサー設定の
attemptToBalanceJumboChunks
では、チャンクにjumboというラベルが付いていない限り、バランサーが大きすぎて移動できないチャンクを移行できます。詳細については、「サイズ制限を超えるバランス範囲」を参照してください。moveRange
とmoveChunk
コマンドを発行するときに、移動できないほど大きい範囲の移行を可能にするために forceJumbo オプションを指定できます。その範囲にはジャンボというラベルが付いている場合と付いていない場合があります。
範囲削除によるパフォーマンスへの影響の調整
rangeDeleterBatchSize
、rangeDeleterBatchDelayMS
、rangeDeleterHighPriority
パラメータを使用して、範囲削除によるパフォーマンスへの影響を調整できます。以下の例をご覧ください。
バッチごとに削除されるドキュメントの数を制限するには、
rangeDeleterBatchSize
を32
などの小さな値に設定します。バッチ削除の合間の時間を延ばすには、現在のデフォルト設定である
20
ミリ秒より大きな値をrangeDeleterBatchDelayMS
に設定します。範囲の削除を優先するには、
rangeDeleterHighPriority
をtrue
に設定します。範囲の削除はバックグラウンドで行われるタスクであり、長時間かかる場合があります。また、システムに高い負荷がかかることで、ユーザーによる操作のスループットに影響が及ぶ可能性があります。
注意
削除対象のコレクションで読み取り操作が進行中であったり、カーソルが開いていると、範囲削除プロセスが続行されないことがあります。
Change Streams と孤立したドキュメント
MongoDB 5.3 以降では、範囲移行中に、孤立したドキュメントの更新に対して変更ストリームイベントは生成されません。
シャードサイズ
MongoDB は、デフォルト設定により、データセットが大きくなるにつれて、利用可能なディスク スペースすべてをシャードのデータで埋めようとします。データの増加に対応できる容量をクラスターで常に確保するには、ディスク使用量やその他のパフォーマンス メトリクスをモニターしてください。
シャードの最大サイズを設定する方法については、「任意のシャードの最大ストレージ サイズを変更する」をご覧ください。
チャンク サイズとバランシング
chunkSize
の概要については、「シャーディングされたクラスターの範囲サイズの変更」をご覧ください。
以下の表では、さまざまな MongoDB バージョンで chunkSize
がデフラグとバランサー操作に与える影響を説明しています。
MongoDB バージョン | 説明 |
---|---|
MongoDB 6.0 以降 | 2 つのシャード間で共有されるコレクション データが、 たとえば、 |
MongoDB 6.0 より前 | チャンクが chunkSize より大きくなると、チャンクが分割されます。 |
チャンクが移動、分割、マージされると、コンフィギュレーションサーバーによってチャンク操作がコミットされた後にシャード メタデータが更新されます。チャンク操作に関係のないシャードも新しいメタデータで更新されます。
シャード メタデータの更新にかかる時間は、ルーティング テーブルのサイズに比例します。コレクションの CRUD 操作は、シャード メタデータが更新される間一時的にブロックされ、ルーティング テーブルが小さいほど CRUD 操作の遅延が短くなります。
コレクションをデフラグすると、チャンクの数が減り、チャンク メタデータの更新にかかる時間が短縮されます。
システム負荷を軽減するには、シャード バランシング ウィンドウを使用して特定の時間にのみバランサーを実行するように設定します。デフラグはバランシング ウィンドウの時間に実行されます。
chunkDefragmentationThrottlingMS
パラメータを使用すると、バランサーによって実行される分割コマンドとマージ コマンドのレートを制限できます。
デフラグはいつでも開始および停止できます。
シャード ゾーンを設定することもできます。シャード ゾーンはシャードキーに基づいており、各ゾーンをクラスター内の 1 つ以上のシャードに関連付けることができます。
MongoDB 6.0 以降、シャーディングされたクラスターは、チャンクの移行が必要な場合のみチャンクを分割するようになりました。これにより、チャンク サイズが chunkSize
を超える場合があります。サイズの大きいチャンクの場合はシャード上のチャンク数を減らし、シャード メタデータの更新にかかる時間を短縮することでパフォーマンスを向上させます。たとえば、chunkSize
を 256 MB に設定しても、シャード上のチャンクが 1 TB と表示される場合があります。
chunkSize
は以下に影響します。
2 つのシャード間における 1 回のチャンク移行操作でバランサーが移行を試みるデータの最大量。
デフラグ中に移行されるデータの量。
シャーディングされたコレクションのデフラグについて詳しくは、「シャーディングされたコレクションのデフラグ」をご覧ください。