...

ウェブホスティングにおけるメモリの断片化:PHP および MySQL のパフォーマンスの落とし穴

メモリの断片化 ウェブホスティングでは、十分な RAM が利用可能であるにもかかわらず、メモリが多くの小さなブロックに分割され、より大きな割り当てが失敗するため、PHP‑FPM および MySQL の速度が低下します。フラグメンテーションがリクエストのコストを増加させ、スワップをトリガーする理由、および PHP および MySQL のロード時間、信頼性、スケーラビリティを明らかに向上させるための、PHP および MySQL の的を絞ったチューニングの必要性について、実践的な例を挙げて説明します。.

中心点

  • ピーエッチピーエフピーエム リサイクル:pm.max_requests によってプロセスを定期的に再起動する
  • バッファ 投与量:MySQLの接続ごとのバッファは控えめに設定する
  • スワップ 回避方法:スワップ性を低下させ、NUMA に注意する
  • メンテナンス:Data_free を確認し、的を絞って最適化
  • モニタリング 活用:トレンドをいち早く見極めて行動する

ホスティングの日常業務において、メモリの断片化とはどういう意味があるのでしょうか?

ホスティングで出会う フラグメンテーション 長時間のプロセスは、常にメモリを要求して解放するため、アドレス空間にギャップが生じます。空き RAM の合計は大きいように見えますが、大きな割り当てに必要な連続したブロックが不足しているため、割り当ての試行が遅くなります。 これは、PHP‑FPM ワーカーや mysqld で、数時間経つと「肥大化」しているように見えることで確認できます。この影響により、各リクエストのコストがわずかに高くなり、負荷がかかると応答時間が著しく長くなります。その結果、CPU やネットワークに問題がないにもかかわらず、セールやバックアップなどのピーク時にパフォーマンスが低下します。.

PHP-FPM が断片化を引き起こす理由

各 PHP‑FPM ワーカーは、コード、プラグイン、およびデータを独自の アドレス空間, 、さまざまなリクエストを処理し、解放時に散在するギャップを残します。時間の経過とともにプロセスは成長し、内部ではメモリを解放しますが、必ずしもオペレーティングシステムに解放するわけではないため、断片化が進みます。さまざまなスクリプト、インポートジョブ、画像処理が、この混合状態をさらに悪化させ、割り当てパターンの変化につながります。 私は、負荷とトラフィックが一定であるにもかかわらず、RAM の使用量が徐々に増加しているのを観察しています。リサイクルを行わない場合、この内部的な断片化により割り当てが低速化され、訪問者数が多い場合の計画立案が困難になります。.

ロード時間と信頼性に顕著な影響

断片化されたプロセスはより多くの オーバーヘッド メモリ管理において、これは管理バックエンドの速度低下やチェックアウトの遅延として現れます。特に WordPress ショップや大規模な CMS インスタンスは、断片化されたワーカーに多数の同時リクエストが集中すると反応が遅くなります。その結果、タイムアウト、502/504 エラー、NGINX または Apache 側でのリトライの増加が発生します。 私は、応答時間のピーク、RAM ベースラインの上昇、スワップ使用量の急激な増加などの指標から、このような状況を読み取っています。これを無視すると、パフォーマンスが低下し、ユーザーエクスペリエンスが悪化し、重要なファネルでの離脱率が上昇します。.

PHP-FPM を正しく設定する:制限、プール、リサイクル

私は現実的な 限界, 、分離されたプール、および断片化を抑制するための一貫したリサイクル。pm.max_requests は、稼働中の訪問者に影響を与えないよう、ワーカーが定期的に再起動するように設定しています。 トラフィックプロファイルで負荷のピークがある場合には、pm = dynamic がより適していることが多いですが、トラフィックが少ないサイトでは pm = ondemand の方が RAM を節約できます。サイトごとの memory_limit は意図的に控えめに設定し、実際のスクリプトを考慮して調整しています。このトピックについては、以下のトピックで概要を説明しています。 PHPのメモリ制限. さらに、負荷の高いプロジェクトは別のプールに分離して、メモリを大量に消費するプロジェクトがすべてのサイトに影響を与えないようにしています。.

OPcache、プリロード、PHPアロケーターについて

PHP プロセスにおける断片化を抑制するため、私は適切に設計された オペキャッシュ. 広々としていて、でもやりすぎじゃない opcache.memory_consumption と十分な内部化文字列は、リクエストごとの繰り返しの割り当てを減らしてくれる。ヒット率、無駄、残りの容量を観察してるよ。時間の経過とともに無駄が増えたら、ワーカーを無制限に増やすよりも、リロードを計画したほうがいい。 プリロードは、コードベースが適切に準備されている場合、ホットコードをメモリに安定的に保持し、割り当てパターンを平準化することができます。さらに、私は次の点にも注意を払っています。 アロケーターの選択: ディストリビューションによって、PHP‑FPM および拡張機能はさまざまな Malloc 実装で動作します。jemalloc などの代替アロケーターは、一部のセットアップでは断片化を大幅に軽減します。ただし、デバッグ、DTrace/eBPF プロファイリング、およびメモリダンプはアロケーターによって動作が異なるため、私はこのような変更はテストを経てから展開しています。.

画像処理やエクスポートなどのメモリを大量に消費するタスクには、より厳しい制限のある個別のプールを使用することをお勧めします。これにより、メインプールが制御不能に拡大することを防ぎ、断片化を隔離することができます。 さらに、メモリを大量に消費する拡張機能(環境変数など)を制限し、バックプレッシャーを利用しています。大きなバッファを必要とするリクエストは、すべてのワーカーを同時に膨張させるのではなく、スロットリングされるか、非同期キューにオフロードされます。.

MySQL のメモリを理解する:バッファ、接続、テーブル

MySQLでは、グローバル バッファ InnoDB バッファプール、接続ごとのバッファ、および操作ごとに拡大する可能性のある一時構造などです。値が大きすぎると、接続負荷が高い場合に RAM 要件が爆発的に増加し、OS レベルでの断片化が増加します。 さらに、更新や削除によってテーブルが断片化され、Data_free 部分が残って、バッファプールの利用効率が低下するんだ。だから、サイズ、ヒット率、一時ディスクテーブルの数を定期的にチェックしてるよ。次の概要は、典型的な症状を正確に特定して、対策を比較検討するのに役立ってるよ。.

症状 推定原因 測定
RAMは着実に増加し、スワップが開始されます。 バッファプールが大きすぎる、または接続バッファが多すぎる プールを適切なサイズに制限し、接続バッファによって削減する
多くの遅いソート/結合 インデックスの欠落、過剰なソート/結合バッファ インデックスを確認し、ソート/結合は控えめに保つ
テーブル内の大きな Data_free 強力な更新/削除、ページが断片化 的を絞った最適化、アーカイブ、スキーマの合理化
一時ディスクテーブルのピーク tmp_table_size が小さすぎる、または不適切なクエリ 値を適度に上げ、クエリを再構築する

MySQL メモリのチューニング:サイズをオーバーサイズではなく選択する

InnoDB バッファプールは、 オペレーティングシステム ファイルシステムキャッシュとサービスに十分な余裕を確保します。特に、Web と DB を組み合わせたサーバーでは重要です。 sort_buffer_size、join_buffer_size、read_buffer などの接続バッファは、多数の同時接続によって RAM ストームが発生しないように、控えめにスケーリングしています。tmp_table_size および max_heap_table_size は、重要度の低い操作で巨大なインメモリテーブルが要求されないように設定しています。その他の調整項目については、以下をご覧ください。 MySQLのパフォーマンス 有益な示唆。重要なのは、盲目的に増幅して断片化やスワップのリスクを冒すよりも、少し控えめに設定して測定するほうが良いということです。.

InnoDB の詳細:再構築戦略とプールインスタンス

MySQL を内部的に「コンパクト」に保つため、定期的な 再構築 書き込みの割合が高いテーブル向け。ターゲットを絞った OPTIMIZE TABLE(または ALTER によるオンライン再構築)は、データとインデックスを統合し、 Data_free. その際、リビルドは I/O を大量に消費するため、負荷の低い時間帯を選択します。オプション innodb_file_per_table テーブル単位でリビルドを制御できるため、個々の「問題のあるファイル」によってテーブルスペースファイル全体が断片化されるリスクを軽減できるため、私はこの機能を有効にしています。.

私は複数利用しています バッファプールインスタンス (innodb_buffer_pool_instances) をプールサイズと CPU コアに関連付けて、内部ラッチの負荷を軽減し、アクセスを分散します。これにより、並列性が向上するだけでなく、プール内の割り当てパターンも平準化されます。 さらに、リドゥログのサイズとパージスレッドのアクティビティもチェックします。蓄積された履歴はメモリと I/O を占有し、OS レベルでの断片化を悪化させる可能性があるからです。重要なことは、設定を段階的に変更し、測定を行い、レイテンシとエラー率が実際に低下した場合にのみ設定を維持することです。.

スワップを回避する:カーネル設定とNUMA

Linux がアクティブなスワップを開始すると、応答時間が長くなります。 オーダー・オブ・マグニチュード, RAMアクセスが遅いI/Oになるから。vm.swappinessをかなり下げて、カーネルが物理RAMを長く使うようにしてる。マルチCPUホストでは、NUMAトポロジーをチェックして、必要ならインターリーブを有効にして、メモリ使用量の不均一さを減らしてる。背景やハードウェアの影響については、視点が参考になるよ。 NUMAアーキテクチャ. さらに、ページキャッシュの安全マージンも計画しています。なぜなら、キャッシュが枯渇すると、マシン全体の断片化が加速するからです。.

透明な巨大ページ、オーバーコミット、およびアロケーターの選択

透明な巨大なページ (THP) は、データベースでレイテンシのピークを引き起こす可能性があります。これは、大きなページの結合/分割が不適切なタイミングで行われるためです。MySQL の応答が遅すぎる場合は、THP を「madvise」に設定するか、無効にします。同時に、次の点にも注意しています。 オーバーコミット: vm.overcommit_memory の設定が寛大すぎると、断片化によって大きな連続ブロックが希少になった場合に OOM キルが発生するリスクがあります。私は保守的なオーバーコミット設定を好み、カーネルログを定期的にチェックしてメモリ圧迫の兆候がないか確認しています。.

について アロケーターの選択 システムレベルでは、glibc‑malloc、jemalloc、tcmalloc は、断片化に関して異なる挙動を示します。私は常に代替案を個別にテストし、RSS の履歴とレイテンシを測定し、実際のトラフィックでメトリクスが安定している場合にのみ変更を適用しています。その効果は、ワークロード、拡張機能の組み合わせ、OS のバージョンによって大きく異なります。.

断片化を認識する:指標とヒント

私はゆっくりと上昇する ベースライン RAM では、負荷時の 5xx 応答の増加や、管理者アクションの遅延が発生します。PHP-FPM の PM 統計を確認すると、子プロセスが制限に達しているか、または存続時間が長すぎるかがわかります。MySQL では、ヒット率、ディスク上の一時テーブル、およびテーブルごとの Data_free を確認します。 同時に、カーネルのバージョンに応じて、ページフォールト、スワップイン/アウト、メモリ断片化インジケーターなどの OS メトリクスも役立ちます。これらのシグナルを統合することで、パターンを早期に認識し、対策を計画的に実施することができます。.

モニタリングの深化:シグナルを統合する方法

私は相関させる アプリケーション・メトリクス (p95/p99レイテンシ、エラー率) プロセス指標 (RSS je FPM‑Worker、mysqld‑メモリ) および OS値 (ページキャッシュ、スラブ、メジャーフォールト)。PHP‑FPM では、キューの長さ、アクティブ/スポーンされた子プロセス、ワーカーのライフタイムについて、ステータスインターフェースを使用しています。 MySQL では、Created_tmp_disk_tables、Handler_write/Handler_tmp_write、およびバッファプールミスを監視しています。さらに、プロセスマップ (pmap/smaps) を確認して、多くの小さなアリーナが作成されていないかを調べます。私にとって重要なのは、 トレンド志向:個々のピークではなく、数時間/数日間にわたる漸進的な変化によって、断片化が真の脅威となるかどうかが決まります。.

実用的なルーチン:メンテナンスとデータ管理

私は定期的に片づけます データ 対象:期限切れのセッション、古いログ、不要なリビジョン、孤立したキャッシュ。変化の激しいテーブルについては、断片化されたページを統合するために、特定の OPTIMIZE ウィンドウを計画しています。 大規模なインポートジョブや cron ウェーブは、すべてのプロセスが同時に最大バッファを要求しないように、時間的に分散します。プロジェクトが拡大している場合は、メモリを大量に消費するパターンを分離するために、早い段階で Web と DB を分離します。この規律により、メモリの整合性が維持され、バーストレイテンシのリスクが軽減されます。.

サイズを正確に計算する:制限とプールを設計する

実際に利用可能な PHP 用 RAM に基づいて pm.max_children を決定します。そのためには、 平均RSS 実際の負荷(拡張機能と OPcache を含む)でのワーカーの 1 つを計算し、ピーク時の安全マージンを追加します。例:16 GB のホストでは、OS、ページキャッシュ、MySQL に 4~6 GB を予約します。PHP に 10 GB が残り、ワーカーあたり 150 MB であれば、理論的には 66 の子プロセスになります。 実際には、ピーク時の余裕を残すため、この値の 80~90% 程度、つまり 52~58 程度を pm.max_children に設定しています。. pm.max_requests 私は、ワーカーが顕著な断片化に陥る前にリサイクルされるように選択します(コードの組み合わせにもよりますが、多くの場合 500~2,000 の範囲です)。.

MySQL では、私は バッファプール アクティブなデータサイズから、DB全体のサイズからじゃないよ。 重要なテーブルやインデックスは収まるべきですが、OSキャッシュには、バイナリログ、ソケット、静的アセットのための空き容量が必要です。接続バッファについては、現実的な最大並列性を考慮して計算します。200 の接続が可能な場合、接続ごとに合計で数ギガバイトもの容量が爆発的に増加するようなサイズ設定はせず、ピーク時でもスワップの危険性がないような厳しい制限を設定します。.

キュー、画像処理、およびサブジョブの分離

多くの断片化の問題は、次のような場合に発生します。 アルバイト フロントエンドリクエストと同じプールを使用します。エクスポート、クロール、画像変換、検索インデックスの更新には、明確な FPM プールまたは CLI ジョブを使用します。 リミットGD/Imagick による画像操作は、個々の巨大な変換によってアドレス空間全体が「切り刻まれる」ことがないように、適切なリソース制限によってさらに制限しています。ジョブは時間差で計画し、フロントエンドパスを圧迫しないように、それぞれに独自の同時実行制限を設定しています。.

コンテナと仮想化:Cgroups、OOM、バルーン効果

コンテナの中で私は観察する メモリ制限 OOMキラーは特に注意して見てね。断片化があると、ホストにまだRAMが残っていても、プロセスがCgroupの制限に達しやすくなるんだ。pm.max_childrenはコンテナの制限に厳密に合わせて、ピークに対応できるだけの余裕を持たせるようにしてるよ。コンテナ内(またはホスト上)でのスワッピングは、追加の間接処理によってレイテンシのピークが大きくなるから避けてるんだ。 VM では、バルーニングと KSM/UKSM をチェックします。積極的な重複排除は RAM を節約しますが、追加のレイテンシを発生させ、断片化の状況を歪める可能性があります。.

箇条書きのない短いチェックリスト

まず、現実的な目標を設定します。 メモリリミット サイトごとに、ピーク使用量が数日間でどのように変化するかを確認します。その後、PHP-FPM を適切な pm 値と適切な pm.max_requests で調整し、断片化されたワーカーが計画通りに動作するようにします。 MySQL については、一律の拡大ではなく、適切なバッファプールサイズと保守的な接続ごとのバッファに焦点を当てます。カーネル側では、スワップ性を下げ、NUMA 設定を確認し、ページキャッシュ用の予備を空けておきます。最後に、Data_free の異常があるテーブルを評価し、日常業務以外の最適化を計画します。.

簡単にまとめると:事業において重要なこと

メモリの断片化に対して最も大きな効果は、一貫した リサイクル PHP‑FPM‑Worker、適度な制限、クリーンなプール。MySQL は、バッファプールと接続ごとのバッファの適切なサイズ、および整理されたテーブルの恩恵を受けています。 スワップは、スワップ性および NUMA に注意し、ファイルキャッシュ用に空き RAM を確保することで、積極的に回避しています。モニタリングにより、ユーザーが気付く前に潜行的なパターンを発見し、計画的な対応を落ち着いて行うことができます。これらの手段を規律正しく活用することで、ハードウェアをすぐにアップグレードすることなく、PHP および MySQL の速度、信頼性、コスト効率を維持することができます。.

現在の記事