ホームページ  >  記事  >  バックエンド開発  >  PHP は高い同時実行性をどのように解決しますか?

PHP は高い同時実行性をどのように解決しますか?

王林
王林オリジナル
2019-09-19 17:57:084082ブラウズ

PHP は高い同時実行性をどのように解決しますか?

PHP は同時実行性の問題を解決します

複数のスレッドが同じファイルに書き込む場合、「スレッドの安全性」の問題が発生することがわかっています。複数のスレッドが同じコード部分を同時に実行します。各実行の結果が単一スレッドの実行の結果と同じであり、結果が期待どおりであれば、スレッドセーフです)。 MySQL データベースの場合は、独自のロック メカニズムを使用して問題を解決できますが、大規模な同時実行シナリオでは MySQL はお勧めできません。

フラッシュ セールスや飛び込み販売のシナリオでは、「過剰送信」という問題がもう 1 つあります。この点を慎重に制御しないと、過剰な送信が発生します。また、一部の電子商取引会社においては、購入者が商品を購入したにもかかわらず、販売者が注文を有効なものとして認識せず、商品の配送を拒否するという駆け込み購入行為を行っているという話も聞いております。ここでの問題は、必ずしも販売業者が不正であるということではなく、システムの技術レベルでの過剰発行のリスクによって引き起こされる可能性があります。

1, 悲観的ロックのアイデア

スレッド セーフを解決するには多くのアイデアがあり、議論は「悲観的ロック」の方向から始めることができます。 」。

悲観的ロック。つまり、データを変更するときに、外部リクエストからの変更を除外するためにロック状態が採用されます。ロック状態になった場合は、待機する必要があります。

PHP は高い同時実行性をどのように解決しますか?

上記の解決策はスレッド セーフの問題を解決しますが、このシナリオは「高い同時実行性」であることを忘れないでください。言い換えれば、そのような変更リクエストが多数存在し、各リクエストは「ロック」を待つ必要があります。一部のスレッドはこの「ロック」を取得する機会がない可能性があり、そのようなリクエストはそこで終了します。

同時に、このようなリクエストが多数発生するため、システムの平均応答時間が瞬時に増加し、その結果、使用可能な接続の数が枯渇し、システムが例外に陥ります。 。

2. FIFO キューのアイデア

それでは、上記のシナリオを少し変更してみましょう。FIFO (先入力、先出力、先入れ先出し)、この場合、一部のリクエストがロックを取得しないことはありません。これを見ると、マルチスレッドを強制的にシングルスレッドにするような感じでしょうか?

PHP は高い同時実行性をどのように解決しますか?

これで、ロックの問題は解決され、すべてのリクエストは「先入れ先出し」キューで処理されます。ここで新たな問題が発生し、同時実行性が高いシナリオでは、リクエストが多数あるため、キューのメモリが瞬時に「爆発」し、システムが異常な状態に陥る可能性があります。

または、巨大なメモリ キューを設計することも解決策ですが、システムがキュー内のリクエストを処理する速度は、キューへの異常な流入の数と比較することはできません。つまり、キューにリクエストがどんどん蓄積されていき、最終的には Web システムの平均応答時間が大幅に低下し、例外状態に陥ることになります。

3. ファイル ロックの考え方

毎日の IP が高くない、または同時実行数がそれほど多くないアプリケーションの場合、通常、ファイル ロックはありません。これを考慮する必要があります!通常のファイル操作方法では全く問題ありません。しかし、同時実行性が高い場合、ファイルの読み書きを行う際に、次のファイルに対して複数のプロセスが動作する可能性が高く、このときにファイルへのアクセスを独占しないと、データ損失が発生しやすくなります

最適化計画 4: ノンブロッキング ファイル排他ロックを使用する

<?php
//优化方案4:使用非阻塞的文件排他锁
include (&#39;./mysql.php&#39;);
//生成唯一订单号
function build_order_no(){
  return date(&#39;ymd&#39;).substr(implode(NULL, array_map(&#39;ord&#39;, str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
    global $conn;
    $sql="insert into ih_log(event,type)
    values(&#39;$event&#39;,&#39;$type&#39;)";
    mysqli_query($conn,$sql);
}
$fp = fopen("lock.txt", "w+");
if(!flock($fp,LOCK_EX | LOCK_NB)){
    echo "系统繁忙,请稍后再试";
    return;
}
//下单
$sql="select number from ih_store where goods_id=&#39;$goods_id&#39; and sku_id=&#39;$sku_id&#39;";
$rs =  mysqli_query($conn,$sql);
$row = $rs->fetch_assoc();
if($row[&#39;number&#39;]>0){//库存是否大于0
    //模拟下单操作
    $order_sn=build_order_no();
    $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
    values(&#39;$order_sn&#39;,&#39;$user_id&#39;,&#39;$goods_id&#39;,&#39;$sku_id&#39;,&#39;$price&#39;)";
    $order_rs =  mysqli_query($conn,$sql);
    //库存减少
    $sql="update ih_store set number=number-{$number} where sku_id=&#39;$sku_id&#39;";
    $store_rs =  mysqli_query($conn,$sql);
    if($store_rs){
      echo &#39;库存减少成功&#39;;
        insertLog(&#39;库存减少成功&#39;);
        flock($fp,LOCK_UN);//释放锁
    }else{
      echo &#39;库存减少失败&#39;;
        insertLog(&#39;库存减少失败&#39;);
    }
}else{
  echo &#39;库存不够&#39;;
    insertLog(&#39;库存不够&#39;);
}
fclose($fp);
 ?>

上記の内容は参考用です。

推奨チュートリアル: PHP ビデオ チュートリアル

以上がPHP は高い同時実行性をどのように解決しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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