MongoDBクラスターの効率的なシャーディングとスケーリングのためのベストプラクティス

より良いMongoDBシャードキーを選択し、バランシングを監視し、不要なスキャッターギャザー作業を回避するクエリを設計します。

MongoDBクラスタの効率的なシャーディングとスケーリングのベストプラクティス

MongoDBのシャーディングは、コレクションを複数のシャードに分散させることで、1つのレプリカセットがすべてのデータやトラフィックを処理する必要をなくします。これにより実際のスケーリング問題を解決できますが、不適切なシャードキーはホットシャード、遅いスキャッターギャザークエリ、元に戻すのが難しい運用作業を引き起こす可能性があります。

シャーディングは、インデックス、スキーマ設計、ハードウェアサイジング、クエリチューニングといった基本を既に処理した後で、単一のレプリカセットがデータサイズ、書き込みスループット、または読み取りワークロードを処理できなくなった場合に使用します。


シャーディングクラスタのコアコンポーネントの理解

機能的なシャーディングクラスタは、連携して動作するいくつかの相互接続されたコンポーネントに依存しています。

  1. シャード(シャードレプリカセット): 各シャードは通常、データセット全体のサブセットを保持するレプリカセットです。データはこれらのシャード間で分割されます。
  2. クエリルーター(Mongosプロセス): これらのプロセスはクライアントリクエストを受け取り、必要なデータがどのシャードにあるかを(メタデータに基づいて)判断し、クエリをルーティングし、結果を集約してクライアントに返します。これらはステートレスで、高いスケーラビリティを持ちます。
  3. コンフィグサーバー(Configサーバー): これらの専用レプリカセットは、特定のデータチャンクがどこにあるかをmongosプロセスに伝えるメタデータ(クラスタマップ)を保存します。これらはクラスタ運用に不可欠であり、高い可用性を維持する必要があります。

主要戦略1:最適なシャードキーの選択

シャードキーはシャーディングにおける最も重要な決定です。これはデータがシャード間でどのように分割されるかを決定します。適切に選択されたシャードキーは均等なデータ分散と効率的なクエリルーティングをもたらしますが、不適切なキーはホットスポットと不均衡なクラスタを引き起こします。

効果的なシャードキーの特性

理想的なシャードキーは3つの主要な特性を持つべきです。

  1. 高いカーディナリティ: キーは細かい分割を可能にするために多くのユニークな値を持つべきです。カーディナリティが低いと、全体的なチャンク数が少なくなります。
  2. 高い書き込み頻度/均等な分散: 書き込みはすべてのシャードキー値に均等に分散されるべきであり、単一のシャードが過負荷になる(ホットスポット)のを防ぎます。
  3. クエリパターン: クエリは理想的にはシャードキーをターゲットにして、ターゲットクエリ(特定のシャードへのルーティング)を可能にするべきです。すべてのシャードをスキャンする必要があるクエリ(スキャッターギャザークエリ)は著しく遅くなります。

シャーディング方法とその影響

MongoDBは2つの主要なシャーディング方法をサポートしています。

  • ハッシュシャーディング: シャードキー値にハッシュ関数を使用します。これにより、シーケンシャルキーであっても、書き込みを利用可能なすべてのシャードに分散させることで、優れたデータ分散を保証します。高い書き込みスループットが必要で、クエリの局所性が重要でない場合に最適です。
  • レンジベースシャーディング: シャードキーの範囲に基づいてデータを分割します(例:IDが1〜1000のすべてのユーザーはシャードAへ)。クエリパターンが範囲検索(例:日付範囲やアルファベット順のID範囲によるクエリ)と一致する場合に最適です。

⚠️ レンジベースシャーディングに関する警告: データ挿入パターンが厳密に増加するシーケンス(タイムスタンプや自動インクリメントIDなど)に従っている場合、レンジベースシャーディングはすべての書き込みが最新のチャンクに集中し、最後のシャードに重大なホットスポットが発生します。

例:ハッシュシャーディングの適用

userIdのようなフィールドを選択し、クエリが頻繁にそれでフィルタリングする場合、ハッシュ化することで書き込みを均等に分散します。

// データベースとコレクションを選択
use myAppDB

// シャーディングのためにuserIdフィールドをハッシュ化
sh.shardCollection("myAppDB.users", { "userId": "hashed" })

主要戦略2:データ分散とバランシングの管理

完璧なシャードキーでも、データチャンク(シャードに保存されるデータの物理単位)は、進化するクエリパターンや初期負荷の不均衡により、不均等なサイズや分散になる可能性があります。バランサープロセスがこれらのチャンクの移行を処理します。

バランサーの監視

クラスタのバランスメトリクスを監視することが重要です。不均衡なチャンクは、一部のシャードでリソースが十分に活用されず、他のシャードが過負荷になる原因となります。

シェル内でsh.status()コマンドを使用して、移行中のチャンクを含む全体的なステータスを表示します。

バランサーの制御

バランサーは自動的に実行されますが、メンテナンスウィンドウや大規模なバッチインポート中にリソース消費を制御するために一時的に無効にすることができます。

// 現在のステータスを確認
sh.getBalancerState()

// バランシングを一時的に無効化
sh.stopBalancer()

// ... メンテナンスや大規模インポートを実行 ...

// 完了したらバランシングを再開
sh.startBalancer()

ベストプラクティス: バランサーを恒久的に無効にしないでください。無効にする場合は、アプリケーションの成長に伴ってデータが均等に分散されていることを確認するために、定期的なレビューをスケジュールしてください。

チャンクサイズの考慮事項

チャンクが小さすぎると、過剰なメタデータオーバーヘッドが発生し、バランサーが遅くなります。逆に、チャンクが大きすぎると、移行が遅くなり、負荷分散の機会が減少します。

  • デフォルトのチャンクサイズ: MongoDBのデフォルトのチャンクサイズは、多くのクラスタに適しています。変更する前に、使用しているMongoDBバージョンのドキュメントを確認してください。
  • チャンクサイズの調整: チャンクサイズは、移行に時間がかかりすぎる、またはメタデータオーバーヘッドが過剰になるなど、明確な運用上の理由がある場合にのみ変更してください。サポートされる方法はMongoDBのリリースによって異なるため、適用する前に現在のコマンドを確認してください。

主要戦略3:読み取りと書き込みのパフォーマンス最適化

シャーディングは読み取りと書き込みのルーティング方法を変更するため、特定のパフォーマンスチューニングが必要です。

ターゲットクエリ vs スキャッターギャザークエリ

  • ターゲットクエリ: シャードキー(またはレンジシャーディングの場合はシャードキーのプレフィックス)を含むクエリは、mongosルーターがリクエストを1つまたは少数のシャードに直接送信できるため、高速です。
  • スキャッターギャザークエリ: シャードキーを使用しないクエリは、すべてのシャードに送信する必要があり、ネットワークレイテンシと処理オーバーヘッドが増加します。

実践的なヒント: 可能な限りシャードキーを利用するようにアプリケーションクエリを設計してください。広範囲をスキャンする必要があるクエリの場合は、プライマリメンバーから負荷を分離するために、レプリカセットのセカンダリメンバーを優先する読み取り設定の使用を検討してください。

シャーディングクラスタでの読み取り設定

シャーディングクラスタは、クライアントレベルで読み取り設定を処理します。操作の重要度に基づいて、アプリケーションコードが正しく読み取り設定を設定していることを確認してください。

  • primary(デフォルト): 読み取りは各シャードのレプリカセットのプライマリに送られます。
  • nearest 読み取りは、地理的またはネットワーク的にアプリケーションに最も近いレプリカセットメンバーに送られます。
  • secondaryPreferred 読み取りは、セカンダリが利用可能な場合はセカンダリに送られ、利用できない場合のみプライマリに送られます。これは、レポートや分析クエリをプライマリからオフロードするのに便利です。

インデックスの落とし穴を避ける

クエリフィルターやソート操作で頻繁に使用されるフィールド、特にシャードキーとそのプレフィックスフィールドにインデックスが存在することを確認してください。シャード間でインデックスが一貫していないと、1つのシャードがインデックスを使用できない場合に、予期しないスキャッターギャザークエリが発生する可能性があります。


安定性のための運用ベストプラクティス

安定した高性能なシャーディングクラスタを維持するには、継続的な運用上の警戒が必要です。

1. シャードキーの変更

シャードキーは変更にコストがかかるものとして選択してください。実際、通常はそうだからです。最近のMongoDBバージョンでは、古いバージョンよりも多くのシャードキーの改良や一部のシャードキー値の更新がサポートされていますが、ルールはバージョン、キーパターン、トランザクション要件によって異なります。本番トラフィックが開始された後の簡単な書き換えを期待しないでください。

2. コンフィグサーバーの復元力

コンフィグサーバーはクラスタの頭脳です。これらが利用できなくなると、クライアントはデータの場所を特定できなくなり、実質的に運用が停止します。

  • 常にコンフィグサーバーをレプリカセット(最低3メンバー)としてデプロイしてください。
  • コンフィグサーバーに高速ストレージを確保し、アプリケーションのワークロードを負わせないようにしてください。

3. キャパシティプランニング

個々のシャードメンバーのCPU、メモリ、ディスクI/O、ストレージの成長、レプリケーションラグ、チャンク分散を監視して、成長に備えて計画を立ててください。1つの固定された使用率パーセンテージに依存するのではなく、1つのシャードがボトルネックになる前に容量を追加してください。

まとめ

MongoDBのシャーディングはスケーリングツールであり、データモデリングの近道ではありません。書き込みを分散し、最も重要なクエリに一致するシャードキーを選択し、起動後にバランシングを監視し、可能な限りアプリケーションクエリをターゲットに保ってください。