メモリ使用量は、ApsaraDB for MongoDB インスタンスにとって重要な指標です。このトピックでは、ApsaraDB for MongoDB インスタンスのメモリ使用量の確認方法、メモリ使用量が多くなる一般的な原因、および最適化戦略について説明します。
背景情報
ApsaraDB for MongoDB プロセスが開始されると、バイナリファイルと依存するシステムライブラリをメモリにロードし、クライアント接続管理、リクエスト処理、ストレージエンジンなどのタスクのためにメモリの割り当てと解放を管理します。 デフォルトでは、ApsaraDB for MongoDB は、メモリ アロケータとして Google の tcmalloc を使用します。 メモリは主にWiredTiger ストレージエンジンとクライアント接続とリクエスト処理によって消費されます。
メモリ使用量の確認
モニタリングチャートの分析
ApsaraDB for MongoDB コンソールのMonitoring Information ページで、ApsaraDB for MongoDB のメモリ使用量を確認できます。ApsaraDB for MongoDB インスタンスのノード構成は、インスタンスアーキテクチャによって異なります。特定のノードを選択して、そのメモリ使用量を確認できます。
レプリカセットアーキテクチャ:プライマリーノード、1 つ以上のセカンダリノード、非表示ノード、およびオプションで 1 つ以上の読み取り専用ノードで構成されます。
シャードクラスターアーキテクチャ:各シャードのメモリ使用量はレプリカセットと同様です。Config Server は設定メタデータを格納します。mongos ルーティングノードのメモリ使用量は、集計結果セットのサイズ、接続数、およびメタデータのサイズに関連しています。
コマンドラインの使用
mongo シェルを使用してインスタンスに接続し、
db.serverStatus().memコマンドを実行してメモリ使用量を表示および分析します。出力例を次に示します。
{ "bits" : 64, "resident" : 13116, "virtual" : 20706, "supported" : true }
// resident は、mongod プロセスが使用する物理メモリ (MB) を示します。
// virtual は、mongod プロセスが使用する仮想メモリ (MB) を示します。serverStatus の詳細については、「serverStatus」をご参照ください。
一般的な原因
エンジンのメモリ
ApsaraDB for MongoDB インスタンスでは、メモリの大部分がストレージエンジンキャッシュとして使用されます。 互換性とセキュリティを確保するため、ApsaraDB for MongoDB は WiredTiger CacheSize をインスタンスの合計割り当てメモリの約 60% に設定します。 仕様の詳細については、「製品仕様」をご参照ください。
ストレージエンジンのキャッシュ使用量が設定された CacheSize の 95% に達すると、インスタンスは高負荷状態となり、ユーザーリクエストを処理するスレッドがクリーンページのエビクションを開始します。ストレージエンジンキャッシュ内のダーティデータが CacheSize の 20% を超えると、ユーザースレッドもダーティページをエビクションします。このプロセス中、ユーザーには顕著なリクエストのブロッキングが発生する可能性があります。ルールの詳細については、「エビクションパラメーター」をご参照ください。
次の方法で、エンジンのメモリ使用量を確認できます。
WiredTiger ストレージエンジンのメモリ使用量の確認
mongo シェルで、
db.serverStatus().wiredTiger.cacheコマンドを実行します。出力フィールドbytes currently in the cacheは、キャッシュによって使用されているメモリ量を示します。次のコードは、出力例を示しています。{ ...... "bytes belonging to page images in the cache":6511653424, "bytes belonging to the cache overflow table in the cache":65289, "bytes currently in the cache":8563140208, "bytes dirty in the cache cumulative":NumberLong("369249096605399"), ...... }
WiredTiger エンジンのキャッシュダーティ率の確認
Database Autonomy Service (DAS) コンソールの [リアルタイム監視データ] ページには、WiredTiger エンジンのリアルタイムキャッシュダーティ率が表示されます。
ApsaraDB for MongoDB に含まれる mongostat ツールを使用して、WiredTiger エンジンの現在のキャッシュのダーティ率を確認します。詳細については、「mongostat」をご参照ください。
接続とリクエストのメモリ
インスタンス上の接続数が多いと、以下の理由で大量のメモリを消費する可能性があります。
スレッドスタックのオーバーヘッド:各接続には、リクエストを処理するための対応するバックエンドスレッドがあります。各スレッドは最大 1 MB のスタック領域を消費する可能性がありますが、通常の使用量は数十から数百キロバイトの範囲です。
TCP 接続カーネルバッファ: カーネルレベルでは、各 TCP 接続には、tcp_rmem や tcp_wmem などの TCP カーネルパラメーターによって決定される読み取りバッファと書き込みバッファがあります。このメモリを管理する必要はありません。ただし、同時接続数が増加し、デフォルトのソケットバッファが大きくなると、TCP メモリ消費量が増加します。
tcmalloc メモリ管理:リクエストが受信されると、リクエストコンテキストが作成され、リクエストパケット、レスポンスパケット、ソートなどのタスクのために一時バッファが割り当てられます。リクエストが完了すると、これらのバッファは tcmalloc メモリアロケーターに解放されます。tcmalloc は、このメモリを自身のキャッシュに返すことを優先し、その後徐々にオペレーティングシステムに解放します。多くの場合、メモリ使用量が高くなるのは、tcmalloc が OS にメモリを速やかに返さないことが原因で、未解放のメモリが数十ギガバイトにまで蓄積される可能性があります。
次の方法で原因を調査できます。
接続使用量の確認
ApsaraDB for MongoDB コンソールのMonitoring Informationページで、お使いのApsaraDB for MongoDBインスタンスの接続使用量を確認します。
mongo シェルで、「接続数」を確認します。
tcmalloc によって保持されているメモリ量の確認
db.serverStatus().tcmallocコマンドを実行して、tcmalloc がオペレーティングシステムに返していないメモリ量を確認します。 tcmalloc キャッシュサイズは、次の式を使用して計算できます: tcmalloc cache = pageheap_free_bytes + total_free_byte。 次のコードは、出力例です。{ ...... "tcmalloc":{ "pageheap_free_bytes":NumberLong("3048677376"), "pageheap_unmapped_bytes":NumberLong("544994184"), "current_total_thread_cache_bytes":95717224, "total_free_byte":NumberLong(1318185960), ...... } }説明tcmalloc の詳細については、「tcmalloc」をご参照ください。
メタデータのメモリ
ApsaraDB for MongoDB インスタンスにデータベース、コレクション、インデックスが多数存在すると、関連するメタデータによって大量のメモリが消費されます。以前のバージョンの ApsaraDB for MongoDB では、次のような問題が発生する可能性があります。
4.0 より前の ApsaraDB for MongoDB バージョンでは、完全な論理バックアップを実行すると多数のファイルハンドルが開かれることがあります。これらのハンドルが速やかにオペレーティングシステムに返されない場合、メモリ使用量が急増する可能性があります。
ApsaraDB for MongoDB 4.0 以前では、多数のコレクションを削除しても、対応するファイルハンドルが適切に削除されず、メモリリークが発生する可能性があります。
インデックス作成のメモリ
通常のデータ書き込み中、セカンダリノードは oplog 適用のために最大約 256 MB のバッファを維持します。しかし、セカンダリノードでインデックス作成操作をレプリケートすると、より多くのメモリを消費する可能性があります。
4.2 より前の ApsaraDB for MongoDB バージョンでは、インデックス作成は
backgroundオプションをサポートしています。{background:true}を指定すると、インデックスはバックグラウンドで構築されます。この操作のレプリケーションはシリアルであり、最大 500 MB のメモリを消費する可能性があります。ApsaraDB for MongoDB 4.2 以降では、
backgroundオプションは非推奨です。セカンダリノードはインデックス作成操作を並行してレプリケートできるため、より多くのメモリを消費します。複数のインデックスを同時に作成すると、メモリ不足 (OOM) エラーが発生する可能性があります。
インデックス作成中のメモリ消費の詳細については、「データベースパフォーマンスへのインデックス構築の影響」および「インデックス構築プロセス」をご参照ください。
プランキャッシュのメモリ使用量
一部のシナリオでは、単一のクエリに多数の候補実行プランが存在する場合があり、その結果、プランキャッシュが大量のメモリを消費する可能性があります。
プランキャッシュのメモリ使用量の確認: ApsaraDB for MongoDB 4.0 以降では、db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes コマンドを実行してメモリ使用量を確認できます。
お使いのインスタンスで ApsaraDB for MongoDB 4.0 が実行されていますが、コマンドが
planCacheTotalSizeEstimateBytesフィールドを返さない場合、インスタンスのマイナーバージョンが古すぎるため、マイナーバージョンをアップグレードすることを推奨します。プランキャッシュのメモリ使用量の詳細については、「バランサー動作中のセカンダリノードにおけるメモリ増加」をご参照ください。
最適化戦略
メモリの最適化は、あらゆるコストを払ってメモリ使用量を最小限に抑えることではありません。むしろ、リソース使用率とパフォーマンスのバランスを取りながら、システムが安定して効率的に動作するのに十分なメモリを確保することが重要です。
ApsaraDB for MongoDB では CacheSize が指定されており、この値を変更することはできません。メモリ使用量を最適化するには、以下の方法があります。
同時接続を制御します。パフォーマンステストによると、データベースは 100 の永続的な接続をサポートでき、デフォルトの MongoDB ドライバーは 100 の接続プールを確立できます。多くのクライアントが接続している場合は、各クライアントのプールサイズを減らす必要があります。データベース全体への永続的な接続の総数を 1,000 未満に保つことを推奨します。接続が過剰になると、メモリとコンテキストスイッチのオーバーヘッドが増加し、リクエストのレイテンシーが上昇する可能性があります。
個々のリクエストのメモリオーバーヘッドを削減します。たとえば、インデックスを作成してコレクションスキャンとメモリ内ソートを減らすことで、クエリパフォーマンスを最適化します。
クエリと接続の最適化後もメモリ使用量が増加し続ける場合は、インスタンスのメモリ仕様をアップグレードします。これにより、過剰なキャッシュエビクションによる潜在的なメモリ不足 (OOM) エラーやパフォーマンスの低下を防ぐことができます。
tcmalloc によるメモリ解放を高速化します。データベースインスタンスのメモリ使用量が 80% を超える場合は、コンソールの パラメーター設定 ページで tcmalloc 関連のパラメーターを調整できます。
まず、
tcmallocAggressiveMemoryDecommitパラメーターを有効にします。このパラメーターは広範囲にテストされており、メモリ保持の問題を効果的に解決します。上記で期待した結果が得られない場合は、
tcmallocReleaseRateパラメーターの値を徐々に増やします。たとえば、1 から 3 に、そして 5 に増やします。
重要これらのパラメーターは、オフピーク時に調整してください。
tcmallocAggressiveMemoryDecommitおよびtcmallocReleaseRateパラメーターを変更すると、データベースのパフォーマンスが低下する可能性があります。ビジネスに影響がある場合は、すぐに変更を元に戻してください。ビジネスへの影響とその許容範囲を判断するには、調整前後に CPU 使用率、レスポンスタイム (RT)、
opCountersなどのメトリックを監視してください。
データベースとコレクションの数を最適化します。インスタンスにデータベースとコレクションが多すぎる場合は、不要なコレクションとインデックスを削除し、複数のテーブルからデータを統合し、インスタンスを分割するか、シャードクラスターに移行できます。詳細については、「データベースとテーブルの数が多すぎるためにインスタンスのパフォーマンスが低下または異常になる」をご参照ください。
ApsaraDB for MongoDB の使用中に、ApsaraDB for MongoDB が関わる可能性のある他のシナリオに遭遇した場合は、Alibaba Cloud テクニカルサポートにお問い合わせください。
参考資料
エビクションパラメーター
パラメーター | デフォルト | 説明 |
| 80% | キャッシュ使用量がeviction_targetを超えると、バックグラウンドエビクションスレッドがクリーンページのエビクションを開始します。 |
| 95% | キャッシュ使用量が eviction_trigger を超えると、ユーザースレッドもクリーンページの解放を開始します。 |
| 5% | ダーティキャッシュ率が eviction_dirty_target を超えると、バックグラウンドの退避スレッドがダーティページの退避を開始します。 |
| 20% | ダーティキャッシュ率が eviction_dirty_trigger を超えると、ユーザースレッドもダーティページの退避を開始します。 |
| 2.5% | キャッシュ更新率が eviction_updates_target を超えると、バックグラウンドのエビクションスレッドが、小さなオブジェクトに関連するメモリフラグメントを追い出し始めます。 |
| 10% | キャッシュ更新率が eviction_updates_trigger を超えると、ユーザースレッドも小さいオブジェクトのメモリフラグメントの削除を開始します。 |
よくある質問
Q:MongoDB で集計操作のメモリ制限を増やすにはどうすればよいですか?
A: ApsaraDB for MongoDB では、集計操作のメモリ制限を直接増やすことはできません。MongoDB の 集計パイプライン の各ステージには 100 MB のメモリ制限があります。ステージがこの制限を超えると、システムはエラーを返します。この問題は、集計パイプラインで {allowDiskUse:true} オプションを明示的に指定することで解決できます。MongoDB 6.0 以降のバージョンでは、グローバルデフォルトパラメーターである allowDiskUseByDefault がサポートされています。集計操作で過剰なメモリが必要になると、MongoDB は自動的に一時ディスク領域を使用して、高いメモリ消費を回避します。メモリ使用量を削減するための他の戦略については、「最適化戦略」をご参照ください。