ホームページ  >  記事  >  バックエンド開発  >  PHP が大規模なタスクを実行するときに効率を向上させるにはどうすればよいでしょうか?

PHP が大規模なタスクを実行するときに効率を向上させるにはどうすればよいでしょうか?

WBOY
WBOYオリジナル
2016-08-18 09:15:361174ブラウズ

1 日に 1 回実行されるタスクをスケジュールする php があります。 ロジックは次のとおりです。
1. データベースに接続し、データベースから関連するデータを配列に読み込みます。
2. データの量に応じてループします。ループの途中には 3 つの mysql 操作 (それぞれ選択、挿入、更新) が含まれています
3. ループの後にデータベース接続を閉じます。

ループの実行数はステップ 1 の mysql_num_rows によって異なり、基本的には数千または数万です。

その後、ループ プロセス中に、何千もの X3 データベース操作が短期間に継続的に実行されるため、非常に非効率的になります。また、複数のタスクはサイクル数の関係で完了までに時間がかかるため、nginx で 504 エラーが発生します。
さらに、頻繁なデータベース操作と長時間の接続により多くのリソースが占有され、環境全体の効率が低下します。

それを最適化するには?

アドバイスをお願いします、よろしくお願いします

返信内容:

1 日に 1 回実行されるタスクをスケジュールする php があります。 ロジックは次のとおりです。

1. データベースに接続し、データベースから関連するデータを配列に読み込みます。
2. データの量に応じてループします。ループの途中には 3 つの mysql 操作 (それぞれ選択、挿入、更新) が含まれています
3. ループの後にデータベース接続を閉じます。
ループの実行数はステップ 1 の mysql_num_rows によって異なり、基本的には数千または数万です。

その後、ループ プロセス中に、何千もの X3 データベース操作が短期間に継続的に実行されるため、非常に非効率的になります。また、複数のタスクはサイクル数の関係で完了までに時間がかかるため、nginx で 504 エラーが発生します。

さらに、頻繁なデータベース操作と長時間の接続により多くのリソースが占有され、環境全体の効率が低下します。

最適化するにはどうすればよいですか?

アドバイスをお願いします、よろしくお願いします


あなたが言及した状況では、問題を解決するためにリクエストを使用しないことをお勧めします。データベースにクエリを実行するときに、バックグラウンドで php スクリプトを実行するスケジュールされたタスクを追加します (合計 100,000 項目など)。 、一度に 1,000 個のアイテムを 1 つずつ処理する必要があり、速度がそれほど速くない場合は、最初に配列に入れてからループすることを避けるために、fetch_row 中に処理することをお勧めします。実装に基づいて、set_time_limit とデータベース接続のタイムアウトを忘れないようにしてください。

少し大量のデータを伴うこの種の長期タスクについてのいくつかの考え:

1. Web 環境は長期タスクには適していません。nginx+php-fpm のアーキテクチャは、長時間のタスクの実行には適していません。期間タスク、および中間 さまざまなタイムアウトは人々を苦しめる可能性があります。少なくとも、単純な set_time_limit(0) でタイムアウトを制御できるため、Apache + PHP の方が優れています。

2. タスクのスケジューリングは Web 経由で実装されます。ほとんどの PHP フレームワークには適切なコマンド ライン サポートがないか、実装時にコマンド ライン サポートが考慮されていないため、Web ベースのタスク分散メカニズムの実装が容易になります。 help 既存のフレームワークの煩わしさは大幅に軽減され、安定したプロジェクトのためには、統一された入り口を確保することが非常に重要です。タスクをコマンド ラインで実行する場合、考慮すべき問題が数多くあります。一般に、Web プロジェクトは Apache などのユーザーによって実行され、生成されたファイルの所有者も Apache になります。ログインが許可されていても、Apache ユーザーとしてコマンドを実行することは可能ですが、それはより複雑です。
3. 分割して征服する: 長期的なタスクに対処するための 1 つの解決策は、大きなタスクを小さなタスクに分割し、長期的なタスクを複数の短期的なタスクに変換し、リソースが占有する時間を削減することです。長期的なタスクに必要な時間。データベース接続のタイムアウトや PHP のメモリ リークなど、時間の実行によって引き起こされるさまざまな問題。

私が書いた例を添付します。アドバイスをお願いします

https://github.com/zkc226/cur...


大量のデータが必要な場合、タスクシステムに引き渡されて実行されます。まず、リクエストが開始され、メッセージ プロデューサはリクエストをコンシューマに渡して処理し、タイムアウトを待たずに戻ります。コンシューマはマルチスレッド処理を実行します。非常に使いやすく、PHP インターフェイスをサポートする Gearman の使用をお勧めします。他にも Workman や Swoole なども実装可能です。

すべての操作は同じサーバーに集中し、同じ時点で実行されます。これは間違いなく時間とリソースを消費します。

@黄红が言ったようにバッチで処理するか、サーバーを追加してこれらのタスクを配置します。他のサーバーに分散して実行する、いわゆる分散処理ですが、データの整合性を確保する必要があるため、タスクが複雑になります

1. データをファイルにエクスポートし、ファイルを読み取り、ループします。 (mysqldump など)
2. 最初にステートメントを綴ってバッチで実行できるかどうかを検討します。すべてのループを実行するのではなく。
3. ストアドプロシージャを使用できるか検討します

また、サイクル数が多いため、複数のタスクが完了するまでに長い時間がかかり、nginx で 504 エラーが表示されます。

リアルタイム計算ですか?大量の計算を伴うタスクの場合、タスクをバックグラウンドで実行して書き込みキャッシュを計算し、リアルタイムで読み取り専用キャッシュを要求することを検討する必要がありますか?

この質問は、効率を向上させるための並列実行について以前に回答した質問に少し似ています

本質は、このビッグデータの読み取りを迂回させ、IDに基づいてモジュロ並列実行を実行することです。たとえば、サーバーとデータベースは20の同時実行に耐えることができます。

並列化する最も簡単な方法は、実行のために 20 個のスクリプト プロセスを開くことです

0.php -> select * from test where id%20=0;
1.php -> select * from test where id%20=1;
2.php -> select * from test where id%20=2;
....

これが引っ張る方法です。

もう 1 つの方法は、それをキューにプッシュし、キューが waker プロセスを呼び出して実行することです。これは、より標準化されており、管理が容易です。たとえば、私が SMS プラットフォームで作業していたとき、上の階にあるギアマンがいます。また、毎日スケジュールされたタスクもあり、これを利用しました。

そのロジックは、おそらく、Gearman クライアントを呼び出して、スケジュールされたタスク スクリプトを開いて、クエリされたすべてのデータを Gearman スケジューラに送信し、その後 20 個のワーカー (LAN 内の同じサーバー上または異なるサーバー上にある可能性があります) を開くというものです。そして、スケジューラはこれら 20 個の Gearman ワーカー スクリプトを実行するように割り当てます。各ワーカー スクリプトのコードは同じであり、1 つのデータと 1 つのタスクの実行になります

タイムアウトしやすいため、WEBメソッドは使用せず、PHPスクリプトをcliモードで処理してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。