たとえば、 server に特定の php ファイルがあるとしますgetProducts.php
。複数のユーザーが同時に要求すると中断されますか? たとえば、ユーザーが製品 A についての詳細を尋ね、別のユーザーが製品 B について、別のユーザーが製品 C について尋ねた場合など... php は中断されますか? それとも、各リクエストに応じて機能し、応答する自己生成スレッドシステムですか?
ありがとうございました!
これは、予想外に、PHP とはほとんど、またはまったく関係がありません。ユーザーの要求に答えるのは PHP ではなく、Web サーバーです。たとえば、Apache、NginX、IIS などです。
次に、Web サーバーは、通常、その瞬間に満たされる他の要求から独立している PHP インスタンスに呼び出しをルーティングします。同時要求の数は、サーバーの構成、アーキテクチャ、およびプラットフォームの機能によって異なります。いわゆる「C10K」サーバーは、最大 1 万の接続を同時に開始できるように設計されています。
しかし、「GET /index.php」から一連の HTML に移行するプロセスの要因は PHP だけではありません。アクティブなページ (PHP、ASP、Python など) は、データベースなどから追加のリソースを要求する場合があります。その場合、同時実行の問題が発生し、2 人のユーザーが同じリソース (データ テーブルの行、テーブル全体、ログ ファイルなど) を取得する必要があるときはいつでも、ある種の セマフォ システムにより、そのうちの 1 つだけが取得されるようになります。それらは一度にその特定のリソースの「ロック」を取得でき、上位の Web サーバーが数百または数千の同時接続を処理できる場合でも、他のすべてのリソースは順番を待つ必要があります。
パフォーマンスの問題の更新: 同じことが、セッションなどの PHP内で発生します。1 人のユーザーが 1 つのページを要求していて、そのページにさらに 10 個の呼び出し (画像、ポップアップ、広告、AJAX など) を生成するコードがあるとします。最初のリクエストでsessionが開かれます。これは、一貫性を維持する必要がある一連のデータです。したがって、他の 10 回の呼び出しがすべて同じセッションにバインドされた場合、PHP はこれらの呼び出しのいずれかがセッション データを変更しようとしているかどうかを知る方法がありません。最初の呼び出しでセッション ロックが解除され、解放されると、2 番目の呼び出しが 3 番目の呼び出しをブロックする、というように続きます。ポイント:避けるsession_start()
必要でない場合 (たとえば、暗号的に強力な GET トークンに置き換えるか、まったく使用しない場合)、またはの値のsession_commit()
変更が完了したらすぐに を呼び出すと、パフォーマンスが大幅に向上します。(より高速なセッション マネージャーや、粗いロックを行わないセッション マネージャーを使用する場合も同様です)。_SESSION
redis
たとえば、画像生成では次のようになります。
session_start();
// This does the magic.
session_commit();
// We can still read session. We just can't write it anymore.
// That's why we needed a session.
if (!isset($_SESSION['authorized'])) {
Header('HTTP/1.1 403 Forbidden');
die();
}
// Here the code that generates an image *and sends* it. The session
// lock, if we hadn't committed, will *not* expire until the request
// has been processed by the *client* with network slowness. (Things
// go much better if you use the CGI interface instead of module).
あなたの例では、「WAMP」タグを見て、Windows Apache が PHP によって MySQL から取得したデータを提供し、製品に対する要求を提供しています。
Apache サーバーは数百の接続を受信し、PHP モジュールの数百のインスタンスをアクティブ化します (それらはほとんどのコードを共有するため、メモリの占有率が急激に上昇することはありません)。製品XYZについて?」. MySQL の用語では、READ LOCK
. 読み取りロックとは、「私はこれを読んでいるので、私が読み終わるまでは誰も書き込みしないでください」というような意味です。しかし、それらはすべて読み取りのみであるため、すべて同時に成功します。
いいえ、停止はありません-ちょうどその時。
しかし、製品ビューのカウンターも更新したいとします。次に、すべての PHP インスタンスにも が必要WRITE LOCK
です。つまり、「このことについて書きたいので、書き終えるまで誰も読んでくれません。そうしないと、中途半端なデータを読む危険があります。もちろん、その間にここに書いてはいけません。私はそれに行きます」。
この時点で、テーブルの種類が重要になります。MyISAM テーブルにはテーブル ロックがあります。製品 A の統計を更新するインスタンスが書き込みを行っている場合、他のインスタンスはそのテーブル全体に対してproduct_views
何も実行できません。それらはすべてキューに入れられて待機します。テーブルが の場合、ロックは行レベルで行われます。製品 A を更新するすべてのインスタンスは、製品 B、C、D などを更新するインスタンスと並行して、次々にキューに入れられます。したがって、すべてのインスタンスが異なるレコードに書き込んでいる場合、それらは並行して実行されます。InnoDB
そのため、これらの場合に InnoDB テーブルを使用する必要があります。
もちろん、「ページ訪問数」などの記録があり、それらがすべて「product-page.php」の行を更新している場合、そこにボトルネックがあり、トラフィックの多いサイトの場合は、その情報を書き込むための別の方法を設計した場合はうまくいきます (多くの回避策の 1 つは、共有メモリの場所に保存することです。時々、それにアクセスする多くのインスタンスの1 つが、情報をデータベースに保存するタスクを受け取ります。インスタンスは引き続きメモリのロックを競合しますが、データベース トランザクションを競合するよりも桁違いに高速です)。
Apache を使用している場合、それは並行システムです。つまり、各リクエストが並行して処理されるため、php スクリプトが中断されることはありません。