PHP の高同時実行テスト: 在庫の売れすぎを防ぐケーススタディ

WBOY
リリース: 2023-04-10 22:46:01
転載
7321 人が閲覧しました

前の記事「PHP での高い同時実行下での製品在庫の売れすぎを防ぐ方法」では、高い同時実行下での製品在庫の売れすぎの防止に関する関連問題について説明しました。一緒に説明しましょう。在庫の売れすぎを防ぐための同時実行テストの関連コンテンツをご覧ください。

PHP の高同時実行テスト: 在庫の売れすぎを防ぐケーススタディ

この記事は、「PHP での同時実行性が高い状況で製品在庫が売れすぎないようにする方法 」のテスト ケースに基づいています。推奨学習: "PHP 学習チュートリアル "

1. 通常の順序

同時テスト中、製品テーブル ID =1 名前 = Daohuaxiang Rice Store = 15

请求总数30 每次10个并发
ab -n 30 -c 10 http://xxxxx.top/code/the_limit/add_order.php
ログイン後にコピー

結果:

在庫削減に成功したのは 15 件で、店舗在庫はマイナスの数値 -7 でした。8 回は在庫が不足していると判断されました (負の在庫数は正しくないため許可されていません)

2. 署名なしモード

製品テーブルに戻る ID =1 名前 = Daohuaxiang Rice Store = 15

请求总数30 每次10个并发
ab -n 30 -c 10 http://xxxxx.top/code/the_limit/unsigned.php
ログイン後にコピー

結果:

在庫削減は 15 回成功し、店舗在庫は -6 のマイナス値になりました。9 回は在庫が不足していると判断されました (マイナスの在庫数は正しくないため許可されません) )

クエリ ステートメントに update を追加するだけでは、ロックにはほとんど効果がありません

3. Mysql トランザクション、ロック操作行

製品テーブル id =1 name = に戻す調整Daohuaxiang Rice store = 15

请求总数30 每次10个并发
ab -n 30 -c 10 http://xxxxx.top/code/the_limit/ACID.php
ログイン後にコピー

結果:

在庫削減に成功したのは 15 回でした。店舗の在庫はマイナスには見えませんでした。在庫がマイナスであると判断されたのは 15 回でした。不十分です (負の在庫数は正しくないため、許可されていません)

トランザクションを追加する効果は良好です。ab -n 3000 -c 1000 の同時実行も許容できます。

4. ノンブロッキング ファイル排他ロック

  • ブロッキング フォーム

  • ノンブロッキング フォーム

効果はマイナスには見えませんが、パフォーマンスの観点: トランザクション > ブロッキング > ノンブロッキング

5. Redis キュー

コードは前のコードと若干異なりますオプティミスティック ロックのバージョンが調整されています

<?php
$redis =new Redis();
$redis->connect("127.0.0.1", 6379);
$redis->auth(&#39;PASSWORD&#39;);
$redis->watch(&#39;sales&#39;);//乐观锁 监视作用 set()  初始值0
$sales = $redis->get(&#39;sales&#39;);
//var_dump($sales); exit;

db();
global $con;
// 查询商品信息
//$product_id = 1;
//$sql = "select * from products where id={$product_id}";
//$result = mysqli_query($con, $sql);
//$row = mysqli_fetch_assoc($result);
//$store = $row[&#39;store&#39;];
// 库存
$n = 15;
if ($sales >= $n) {
    insertLog(&#39;库存为0 秒杀失败&#39;);
    exit(&#39;秒杀结束&#39;);
}

//redis开启事务
$redis->multi();
$redis->incr(&#39;sales&#39;); //将 key 中储存的数字值增一 ,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
$res = $redis->exec(); //成功1 失败0

if ($res) {
    //秒杀成功
    $con = new mysqli(&#39;localhost&#39;,&#39;root&#39;,&#39;PASSWORD&#39;,&#39;dev&#39;);
    if (!$con) {
        echo "数据库连接失败";
    }

    $product_id = 1;// 商品ID
    $buy_num = 1;// 购买数量
    sleep(1);

    $sql = "update products set store=store-{$buy_num} where id={$product_id}";

    if (mysqli_query($con, $sql)) {
        echo "秒杀完成";
        insertLog(&#39;恭喜 秒杀成功&#39;);
    }

} else {
    insertLog(&#39;抱歉 秒杀失败&#39;);
    exit(&#39;抢购失败&#39;);
}

function db()
{
    global $con;
    $con = new mysqli(&#39;localhost&#39;,&#39;root&#39;,&#39;WOrd1234.*&#39;,&#39;dev&#39;);
    if (!$con) {
        echo "数据库连接失败";
    }
}

/**
 * 记录日志
 */
function insertLog($content)
{
    global $con;
    $sql = "INSERT INTO `order_log` (content) values(&#39;$content&#39;)";
    mysqli_query($con, $sql);
}
ログイン後にコピー
ab -n 30 -c 10 http://xxxxxx.top/code/the_limit/optimistic\ _redis_lock.php
ログイン後にコピー

最終結論 同時実行性の課題では、パフォーマンスの良い Redis が優先されます。

推奨される学習: 「PHP ビデオ チュートリアル

以上がPHP の高同時実行テスト: 在庫の売れすぎを防ぐケーススタディの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:learnku.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート