ApsaraDB for MongoDB インスタンスで CPU 使用率が高くなると、クエリの実行が遅延し、放置したままではインスタンスがリクエストの処理を停止する可能性があります。本トピックでは、高 CPU 使用率の一般的な原因と、即時対応から恒久的解決までのステップごとの手順について説明します。
CPU 使用率の測定方法
ApsaraDB for MongoDB コンソール の 監視データ ページから CPU 使用率をモニタリングします。監視間隔および該当ページへの移動手順については、「基本的なモニタリング」をご参照ください。
インスタンス内の各ノードタイプには、それぞれ固有の CPU 使用率メトリクスがあります:
レプリカセットインスタンス — プライマリノード、1 つ以上のセカンダリノード、非表示ノード、および任意の読み取り専用ノードで構成されます。
シャードクラスターインスタンス — 1 つ以上のシャードコンポーネント、ConfigServer コンポーネント、および 1 つ以上の Mongos コンポーネントで構成されます。シャードコンポーネントの CPU 動作は、レプリカセットインスタンスと同一です。ConfigServer は構成メタデータのみを格納し、ほとんどのケースで CPU ボトルネックにはなりません。Mongos の CPU 使用率は、集約結果セットのサイズおよび同時実行リクエスト数に比例して増加します。
CPU 使用率は、常にインスタンスの全コア数に対する割合(パーセント)で表示されます。8 コアのインスタンスで使用率が 100 % である場合、すべての 8 コアが使い尽くされていることを意味します。このメトリクスは 100 % を超えることはありません。
一般的な原因
スキャンされるドキュメント数が多すぎる
ApsaraDB for MongoDB はマルチスレッド方式を採用しています。単一のクエリが大量のドキュメントをスキャンすると、そのスレッドが CPU リソースを長時間占有します。高い同時実行性の状況では、これが蓄積され、全体の CPU 使用率を上昇させます。インスタンスの総 CPU 負荷は、すべてのクエリでスキャンされたドキュメント総数と直接相関します。
過剰なドキュメントスキャンを引き起こす主なパターンは以下の 2 つです:
コレクション全体のフルスキャン(COLLSCAN)
スロークエリログまたは system.profile コレクション内に COLLSCAN が記録されている場合、そのクエリはコレクション内のすべてのドキュメントを読み取ったことを意味します。system.profile コレクションは、データベースプロファイリングを有効化した場合にのみ作成されます。クエリ実行計画の解釈方法については、「Explain Results」および「Cursor Methods」をご参照ください。
非効率なインデックス利用(docsExamined の値が非常に高い)
頻繁に実行されるクエリにおいて docsExamined の値が 1,000 を超える場合、そのクエリは注意を要します。主な原因は以下のとおりです:
複数のフィルター条件に対して結合インデックスが設定されていない、またはインデックスプレフィックスルールが満たされていない。
複雑なクエリや大規模な集約パイプラインにより、インデックスが効果的に活用できない。
データ分布が偏っている(選択性が低い)フィールドをクエリフィルターとして使用している。
高い同時実行性
同時実行リクエスト数が実際に多く、かつクエリに問題がない場合、追加の CPU 容量が必要になります。「CPU 容量の追加」をご参照ください。
その他の原因
短時間接続の集中発生(Connection Storm)
MongoDB 3.X より後のバージョンでは、デフォルトの認証メカニズムが SCRAM-SHA-1 であり、接続ごとに CPU 消費量の多いハッシュ計算を実行します。多数の短時間接続が同時に確立されると、このハッシュオーバーヘッドが倍増し、すべての CPU リソースを枯渇させる可能性があります。運用ログには、この状況下で多数の saslStart エラーメッセージが記録されます。ApsaraDB for MongoDB では、組み込みの RANDOM 関数を最適化することでカーネル層でこのオーバーヘッドを低減しています。
セカンダリノードにおける TTL インデックスの oplog 再生
生存時間(TTL)インデックスを使用してデータの有効期限を管理する場合、MongoDB は削除操作を複数の oplog エントリに変換します。セカンダリノードは、マルチスレッドレプリケーション(replWriterThreadCount パラメーターで制御、MongoDB 3.2 以降ではデフォルト値が 16)によりこれらの oplog を再生します。セカンダリノードはビジネスクリティカルな書き込みワークロードを処理しませんが、oplog 再生は元の書き込みよりも効率が低いため、セカンダリノードの CPU 使用率がプライマリノードより高くなることがあります。このような場合は、当該ノードの高 CPU 使用率を無視しても問題ありません。
高 CPU 使用率のトラブルシューティング
以下の表を参考に、ご自身の状況に最も適したツールを選択してください。
| 目的 | ツール |
|---|---|
| 進行中のスロークエリを直ちに停止する | CloudDBA > セッション、または db.killOp() |
| 事後的にスロークエリを特定する | ログ > スロークエリログ |
| すべてのリクエスト(スローでないものも含む)を監査する | データセキュリティ > 監査ログ |
アクティブセッションの終了
CPU 使用率が 100 % 近くに達している場合、根本原因の調査に先立ち、CPU 使用率の急増を引き起こしているセッションを終了してください。
オプション 1 — ApsaraDB for MongoDB コンソール(推奨)
ApsaraDB for MongoDB コンソール で、対象インスタンスのインスタンス ID をクリックします。
左側のナビゲーションウィンドウから、CloudDBA > セッション を選択します。
アクティブセッションを確認し、予想より長く実行されている操作を特定して終了します。
セッションページでは、シェルアクセスを必要とせず、同一インターフェイス上で操作の表示および強制終了が可能です。これは CPU 使用率が急増している際の最速の対応手段です。
オプション 2 — MongoDB シェル
db.currentOp() を実行してアクティブな操作を一覧表示し、その後 db.killOp() を実行して特定の操作を終了します。構文の詳細については、「db.currentOp()」および「db.killOp()」をご参照ください。
ログの分析による根本原因の特定
即時の CPU 使用率の急増を停止した後、それを引き起こしたクエリを特定します。
監査ログ
ApsaraDB for MongoDB コンソール で、データセキュリティ > 監査ログ を選択して監査ログ機能を有効化します。設定手順については、「監査ログ機能の有効化」をご参照ください。
スロークエリログ
スロークエリログは 7 日間保持されます。2021 年 6 月 6 日以降に購入したインスタンスの場合、監査ログ機能を有効化し、admin および slow の操作タイプを選択したうえで、スロークエリログを閲覧できます。機能を有効化した後に生成されたログのみが利用可能です。
コンソールで、パラメーター > パラメーターリスト を選択し、以下のパラメーターを設定します:しきい値を超えるクエリは
system.profileコレクションに記録されます。パラメーターの詳細については、「Database Profiler」をご参照ください。パラメーター 説明 operationProfiling.modeプロファイリングレベルを設定します:無効(データ収集なし)、すべてのリクエスト(system.profile にデータを記録)、またはスロークエリのみ(しきい値を超えるクエリを system.profile に記録) operationProfiling.slowOpThresholdMsクエリが「スロー」と分類されるしきい値(ミリ秒単位)を設定します ログ > スロークエリログ を選択してログを表示します。
ログ内で以下を確認します:
COLLSCAN— コレクション全体のフルスキャンを示します。docsExaminedの値が予想より大幅に高い — インデックス効率が低いことを示します。
高 CPU 使用率の解決
インデックスの最適化
インデックスの最適化は、クエリごとのスキャンドキュメント数を削減する最も効果的な方法です。COLLSCAN または高い docsExamined 値を示すクエリから着手してください。
インデックス最適化に関するリソース:
結合インデックス — 複数のフィルター条件を持つクエリ向け
cursor.hint() — 特定のインデックスを強制的に使用する
選択性を確保するクエリの作成 — データ分布が偏っているフィールド向け
インデックス化のみでは改善しない場合、影響を受けるコレクションのデータ量を制限するか、フルコレクションスキャンの実行頻度を低下させてください。
CPU 容量の追加
クエリがすでに十分に最適化されており、実際のトラフィック量が原因で CPU 使用率が高い場合は、インスタンスのスケールアップを検討してください。一般的な手法は以下のとおりです:
インスタンスのスケールアップ — 読み取りおよび書き込みの余裕を拡大します。
読み書き分離の有効化、またはレプリカセットインスタンスに読み取り専用ノードを追加 — 読み取り負荷を分散します。
シャードクラスターインスタンスへのアップグレード — 複数のシャードにわたって線形スケールアウトを実現します。
Mongos ノードの追加 — Mongos 層で CPU が枯渇している場合、Mongos ノードを追加し、それらの間で負荷分散を構成します。詳細については、「シャードクラスターの概要」の「Balancer」セクションをご参照ください。
インスタンス構成の変更手順については、以下のリンクをご参照ください:
接続保持の活用
短時間接続では、毎回 SCRAM-SHA-1 認証がトリガーされ、大規模環境では CPU 消費が大きくなります。接続プールを用いて接続を保持することで、接続ごとの認証オーバーヘッドを排除できます。