メモリ使用量は、ApsaraDB for MongoDB の重要な監視メトリックです。このトピックでは、ApsaraDB for MongoDB インスタンスのメモリ使用量を確認する方法、メモリ使用量が多くなる一般的な原因、および最適化戦略について説明します。
概要
ApsaraDB for MongoDB のプロセスが開始されると、バイナリファイルや各種システムライブラリをメモリに読み込むだけでなく、クライアント接続、リクエスト処理、ストレージエンジンのためのメモリ割り当てと解放も管理します。デフォルトでは、ApsaraDB for MongoDB は Google tcmalloc をメモリアロケータとして使用します。メモリは主に、WiredTiger ストレージエンジン、クライアント接続とリクエスト処理によって消費されます。
メモリ使用量の確認
監視チャート
ApsaraDB for MongoDB コンソールの [モニタリングデータ] ページで、データベースアーキテクチャに対応するノードを選択して、そのメモリ使用率を確認します。
レプリカセットアーキテクチャ:1 つのプライマリノード、1 つ以上のセカンダリノード、1 つの Hidden ノード、およびオプションで 1 つ以上の ReadOnly ノードが含まれます。
シャードクラスターアーキテクチャ:各シャードのメモリ使用量はレプリカセットと同じパターンに従います。Config サーバーは構成メタデータを格納します。Mongos ルーティングノードのメモリ使用量は、集約結果セットのサイズ、接続数、およびメタデータのサイズに依存します。
コマンドライン
MongoDB Shell でインスタンスに接続し、
db.serverStatus().memコマンドを実行してメモリ使用量を確認します。以下は応答のサンプルです:
{ "bits" : 64, "resident" : 13116, "virtual" : 20706, "supported" : true }
// resident: mongod プロセスが使用する物理メモリの量 (MB)。
// virtual: mongod プロセスが使用する仮想メモリの量 (MB)。serverStatus の詳細については、「serverStatus」をご参照ください。
一般的な原因
ストレージエンジンのメモリ使用量
メモリの大部分はストレージエンジンキャッシュによって消費されます。互換性とセキュリティ上の理由から、ApsaraDB for MongoDB は WiredTiger CacheSize をインスタンスのメモリ仕様の約 60% に設定します。詳細については、「プロダクト仕様」をご参照ください。
ストレージエンジンキャッシュが設定された CacheSize の 95% を使用する場合、インスタンスの負荷が高いことを示し、ユーザーリクエストを処理するスレッドがクリーンページのエビクションに参加します。ストレージエンジンキャッシュ内のダーティデータがキャッシュサイズの 20% を超えると、ユーザースレッドもダーティページのエビクションに参加します。このプロセス中に、リクエストの大幅なブロッキングが発生することがあります。具体的なルールについては、「エビクションパラメーターの説明」をご参照ください。
以下の方法でエンジンのメモリ使用量を確認できます:
WiredTiger エンジンのメモリ使用量の確認
MongoDB Shell で、次のコマンドを実行します:
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 エンジンのキャッシュのダーティ率の確認
DAS コンソールで、[リアルタイム監視データ] ページに移動して、現在のキャッシュのダーティ率を確認します。
ApsaraDB for MongoDB に付属の mongostat ツールを使用して、現在のキャッシュのダーティ率を確認します。
接続とリクエストのメモリ使用量
インスタンスへの同時接続数が多い場合、以下の理由で大量のメモリを消費する可能性があります:
スレッドスタックのオーバーヘッド:各接続には、その接続上のリクエストを処理するための対応するバックエンドスレッドがあります。各スレッドは最大 1 MB のスタック領域を消費する可能性がありますが、通常は数十から数百 KB の範囲です。
TCP 接続カーネルバッファー:カーネルレベルでは、各 TCP 接続には読み取りおよび書き込みバッファーがあり、これは tcp_rmem や tcp_wmem などのカーネルパラメーターによって決まります。このメモリ使用量を管理する必要はありません。ただし、同時接続数が多く、デフォルトのソケットバッファーが大きいほど、TCP のメモリ消費量は高くなります。
tcmalloc のメモリ管理:リクエストを受信すると、リクエストコンテキストが作成され、一時バッファー (リクエストパケット、応答パケット、一時ソートバッファーなど) が割り当てられます。リクエストが完了すると、これらの一時バッファーは tcmalloc メモリアロケータに返されます。tcmalloc はまず自身のキャッシュにこれらを返し、その後徐々にオペレーティングシステムに解放します。多くの場合、メモリ使用量が高くなるのは、tcmalloc がメモリを速やかに OS に返さないためです。この解放されていないメモリは、数十ギガバイトに達することがあります。
以下の方法でトラブルシューティングを行うことができます:
接続使用量の確認
ApsaraDB for MongoDB コンソールの [モニタリングデータ] ページで、接続使用量を確認します。
MongoDB Shell を使用して接続数をクエリします。
tcmalloc から OS に返却されていないメモリの確認
db.serverStatus().tcmallocコマンドを実行して、tcmalloc が保持しているメモリ量を確認します。このコンテキストでは、tcmalloc キャッシュ = 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), ...... } }
メタデータのメモリ使用量
ApsaraDB for MongoDB インスタンスにデータベース、コレクション、インデックスのメタデータが大量にある場合、かなりのメモリ量を消費する可能性があります。以前のバージョンの ApsaraDB for MongoDB では、以下の問題が発生する可能性があります:
4.0 より前の ApsaraDB for MongoDB では、完全な論理バックアップによって多数のファイルハンドルが開かれることがあります。これらが速やかにオペレーティングシステムに返されない場合、メモリ使用量が急増する可能性があります。
4.0 以前の ApsaraDB for MongoDB では、多数のコレクションを削除しても、対応するファイルハンドルが適切に削除されず、メモリリークにつながる可能性があります。
インデックス作成時のメモリ使用量
通常のデータ書き込み中、セカンダリノードはデータ oplog 適用のために約 256 MB のバッファーを維持します。しかし、インデックスを作成する際、セカンダリノードの oplog 適用プロセスはより多くのメモリを消費する可能性があります。
4.2 より前の ApsaraDB for MongoDB では、インデックス作成は
backgroundオプションをサポートしています。{background:true}が指定されている場合、インデックスはバックグラウンドで構築されます。インデックス作成のための oplog 適用はシリアルであり、最大 500 MB のメモリを消費する可能性があります。ApsaraDB for MongoDB 4.2 以降のバージョンでは、デフォルトで
backgroundオプションは非推奨となっています。セカンダリノードはインデックス作成を並行して適用することが許可されており、これによりより多くのメモリを消費します。複数のインデックスを同時に作成すると、インスタンスで Out of Memory (OOM) エラーが発生する可能性があります。
インデックス作成時のメモリ使用量の詳細については、「Index Build Impact on Database Performance」および「Index Build Process」をご参照ください。
PlanCache のメモリ使用量
一部のシナリオでは、単一のリクエストが多数の潜在的な実行計画を持つことがあり、PlanCache が大量のメモリを消費する原因となります。
PlanCache のメモリ使用量の確認:ApsaraDB for MongoDB 4.0 以降のバージョンでは、db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes コマンドを実行してサイズを確認します。
ご利用の ApsaraDB for MongoDB 4.0 インスタンスで上記のコマンドが関連フィールドを返さない場合、インスタンスは古いマイナーバージョンを実行しています。この機能にアクセスするには、データベースのマイナーバージョンをアップグレードしてください。
PlanCache のメモリ使用量の詳細については、「Secondary node memory arise while balancer doing work」をご参照ください。
最適化戦略
メモリの最適化は、あらゆるコストをかけてメモリ使用量を最小限に抑えることではありません。むしろ、システムが正常に動作するために十分で安定したメモリを確保し、リソース使用率とパフォーマンスのバランスを取ることです。
ApsaraDB for MongoDB は CacheSize を指定しており、この値は変更できません。以下の戦略を使用してメモリ使用量を最適化できます:
同時接続数を制御します。パフォーマンステストの結果に基づくと、データベースサーバーは最大 100 の同時接続をサポートし、MongoDB ドライバーのデフォルトの接続プールサイズは 100 です。複数のクライアントがある場合は、各クライアントの接続プールサイズを減らしてください。インスタンスへの持続的接続の総数を 1,000 未満に保ち、メモリとマルチスレッドのコンテキストスイッチのオーバーヘッドの増加を避け、リクエストレイテンシへの影響を防ぎます。
個々のリクエストのメモリオーバーヘッドを削減するために、インデックスを作成してコレクションスキャンとメモリ内ソートを減らし、クエリパフォーマンスを最適化します。
クエリを最適化し、適切な接続数を設定した後もメモリ使用量が高いままである場合は、メモリ仕様をアップグレードして、過剰なキャッシュエビクションによる潜在的な Out of Memory (OOM) エラーやパフォーマンス低下を防ぎ、インスタンスの可用性を確保します。
tcmalloc によるメモリ解放を高速化します。データベースインスタンスのメモリ使用量が 80% を超える場合は、コンソールの [パラメーター] ページで tcmalloc 関連のパラメーターを調整できます。
まず、
tcmallocAggressiveMemoryDecommitパラメーターを有効にします。このパラメーターは広範囲にテストされており、メモリ関連の問題を解決するのに効果的であることが証明されています。tcmallocReleaseRateパラメーターの値を徐々に増やします。上記のパラメーターを調整しても期待される結果が得られない場合は、tcmallocReleaseRateの値を徐々に増やします (例:1 から 3、次に 5 へ)。
重要これらのパラメーターの調整は、オフピーク時に行ってください。
tcmallocAggressiveMemoryDecommitおよびtcmallocReleaseRateパラメーターを変更すると、データベースのパフォーマンスが低下する可能性があります。ビジネスに影響が出た場合は、直ちに変更をロールバックしてください。データベースとコレクションの数を最適化します。データベースインスタンスにデータベースとコレクションが多すぎる場合は、不要なコレクションとインデックスを削除し、複数のテーブルからデータを統合し、インスタンスを分割するか、シャードクラスターに移行することができます。詳細については、「データベースまたはテーブルが多すぎることによるパフォーマンスの低下」をご参照ください。
ApsaraDB for MongoDB の使用中に他の潜在的なメモリリークシナリオが発生した場合は、Alibaba Cloud テクニカルサポートにご連絡ください。
参考資料
エビクションパラメーターの説明
パラメーター | デフォルト値 | 説明 |
eviction_target | 80% | キャッシュ使用量が eviction_target を超えると、バックグラウンドスレッドがクリーンページのエビクションを開始します。 |
eviction_trigger | 95% | キャッシュ使用量が eviction_trigger を超えると、ユーザースレッドもクリーンページのエビクションを開始します。 |
eviction_dirty_target | 5% | ダーティキャッシュの割合が eviction_dirty_target を超えると、バックグラウンドスレッドがダーティページのエビクションを開始します。 |
eviction_dirty_trigger | 20% | ダーティキャッシュの割合が eviction_dirty_trigger を超えると、ユーザースレッドもダーティページのエビクションを開始します。 |
eviction_updates_target | 2.5% | キャッシュ更新率が eviction_updates_target を超えると、バックグラウンドスレッドが小オブジェクトに関連するメモリフラグメントのエビクションを開始します。 |
eviction_updates_trigger | 10% | キャッシュ更新率が eviction_updates_trigger を超えると、ユーザースレッドも小オブジェクトに関連するメモリフラグメントのエビクションを開始します。 |
FAQ
Q:MongoDB の集約操作のメモリ制限を増やすにはどうすればよいですか?
A:現在、ApsaraDB for MongoDB は集約操作のメモリ制限を直接増やすことをサポートしていません。MongoDB は、集約パイプラインステージごとに 100 MB のメモリ制限を強制します。ステージがこの制限を超えると、システムはエラーを返します。この問題を解決するには、集約パイプラインで {allowDiskUse:true} オプションを明示的に指定します。MongoDB 6.0 以降、MongoDB は allowDiskUseByDefault パラメーターをグローバルに導入しました。集約操作が過剰なメモリを必要とする場合、MongoDB は自動的に一時ディスク領域を使用してメモリ消費を削減します。メモリ使用量を最適化するための追加の戦略については、「最適化戦略」をご参照ください。