• 技术文章 >后端开发 >php教程

    php高并发测试:防止库存超卖的案例讲解

    长期闲置长期闲置2022-04-14 09:58:04转载945
    在之前的文章《PHP高并发情形下怎么防止商品库存超卖》中,我们讲到了关于在高并发情况下防止商品库存超卖的相关问题,下面我们一起来看一下防止库存超卖之并发测试的相关内容,希望对大家有帮助。

    本文是基于《PHP高并发情形下怎么防止商品库存超卖》的测试案例。推荐学习:《PHP学习教程

    一、 普通下单

    并发测试时 product 表 id =1 name = 稻花香大米 store = 15

    请求总数30 每次10个并发
    ab -n 30 -c 10 http://xxxxx.top/code/the_limit/add_order.php

    结果:

    有 15 次库存减少成功 store 库存出现了负数 -7 8 次判断为库存不够 (库存负数是不正确的 不允许的)

    二、unsigned 模式

    调整回 product 表 id =1 name = 稻花香大米 store = 15

    请求总数30 每次10个并发
    ab -n 30 -c 10 http://xxxxx.top/code/the_limit/unsigned.php

    结果:

    有 15 次库存减少成功 store 库存出现了负数 -6 9 次判断为库存不够 (库存负数是不正确的 不允许的)

    仅在查询语句上 加 for update 加锁效果不大

    三、mysql 的事务,锁住操作的行

    调整回 product 表 id =1 name = 稻花香大米 store = 15

    请求总数30 每次10个并发
    ab -n 30 -c 10 http://xxxxx.top/code/the_limit/ACID.php

    结果:

    有 15 次库存减少成功 store 库存未出现负数 15 次判断为库存不够 (库存负数是不正确的 不允许的)

    加事务 效果不错 ab -n 3000 -c 1000 并发也能扛住

    四、 非阻塞的文件排他锁

    效果也没有出现负数 但性能上:事务 > 阻塞 > 非阻塞

    五、 redis 队列

    代码与之前 略有调整 乐观锁版

    <?php
    $redis =new Redis();
    $redis->connect("127.0.0.1", 6379);
    $redis->auth('PASSWORD');
    $redis->watch('sales');//乐观锁 监视作用 set()  初始值0
    $sales = $redis->get('sales');
    //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['store'];
    // 库存
    $n = 15;
    if ($sales >= $n) {
        insertLog('库存为0 秒杀失败');
        exit('秒杀结束');
    }
    
    //redis开启事务
    $redis->multi();
    $redis->incr('sales'); //将 key 中储存的数字值增一 ,如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
    $res = $redis->exec(); //成功1 失败0
    
    if ($res) {
        //秒杀成功
        $con = new mysqli('localhost','root','PASSWORD','dev');
        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('恭喜 秒杀成功');
        }
    
    } else {
        insertLog('抱歉 秒杀失败');
        exit('抢购失败');
    }
    
    function db()
    {
        global $con;
        $con = new mysqli('localhost','root','WOrd1234.*','dev');
        if (!$con) {
            echo "数据库连接失败";
        }
    }
    
    /**
     * 记录日志
     */
    function insertLog($content)
    {
        global $con;
        $sql = "INSERT INTO `order_log` (content) values('$content')";
        mysqli_query($con, $sql);
    }
    ab -n 30 -c 10 http://xxxxxx.top/code/the_limit/optimistic\ _redis_lock.php

    最终结论 并发挑战 优先 redis 性能好

    推荐学习:《PHP视频教程

    以上就是php高并发测试:防止库存超卖的案例讲解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:learnku,如有侵犯,请联系admin@php.cn删除
    专题推荐:php
    上一篇:如何配置php.ini,进行PHP性能调优? 下一篇:PHP基础巩固之基础语法、变量和常量(总结分享)
    Web大前端开发直播班

    相关文章推荐

    • PHP中mysql_connect()函数不支持怎么办• 实例详解thinkphp6搭建后端api接口• 被唱衰的PHP,在这份排行榜一直稳坐第四!• 详细解析PHP反序列化漏洞• thinkphp5怎么判断变量是否为空

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网