欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

验证MySQL乐观锁与悲观锁并发情况

程序员文章站 2022-05-04 15:31:35
...

目标:验证谁更加能扛并发;

模拟场景,秒杀;

乐观锁实现

代码:

    //悲观锁扣库存
    public function test28(){
        /**
         * 1:查询库存数量
         * 2:判断是否可以购买(不可购买则退出循环)
         * 3:满足条件则减少对应库存,并记录拿到第多少个商品,提交并退出循环
         * 4:否则重试第1步
         */
        Db::startTrans();
        $i=1;
        do{
            $stock=TStock::where('id','=',1)->find();
            if ($stock->stock-1>=0){
                //有货
                //返回受影响条数
                $re=TStock::where('id','=',1)->where('stock','=',$stock->stock)->setDec('stock',1);
                if ($re===1){
                    //更新成功
                    TResult::insert(['value1'=>$stock->stock,'value2'=>$i]);//记录拿到第几个,第几次成功
                    Db::commit();
                    echo "第 $i 次成功!<br/>";
                    break;
                }else{
                    //更新失败---重试
                    echo "第 $i 次重试中.....<br/>";
                }
            }else{
                //没货了
                Db::rollback();
                echo "没货了<br/>";
                break;
            }
            $i++;
            if ($i>1000){
                echo '老子不要了,太难抢了!<br/>';
                Db::rollback();
                break;//高并发时候,乐观锁性能消耗巨大,改善:将消息加入队列处理
            }
        }while(true);
    }

ab测压结果:单纯乐观锁是个鸡肋

验证MySQL乐观锁与悲观锁并发情况
运行了好几次ab测压命令,才抢到15条,单纯乐观锁,基本没用,除非第一次就抢到,否者基本抢不到。就算配合消息队列处理,这也不是乐观锁本身扛并发了(难怪网上说成熟大网站才用乐观锁)。

悲观锁实现

    //悲观锁实现
    public function test29(){
        /**
         * 1:查询库存数量,并锁住记录
         * 2:判断是否可以购买(不可购买则退出)
         * 3:满足条件则减少对应库存,并记录拿到第多少个商品,提交
         */
        Db::startTrans();
        $stock=TStock::where('id','=',1)->lock(true)->find();
        if ($stock->stock-1>=0){
            TStock::where('id','=',1)->setDec('stock',1);
            TResult::insert(['value1'=>$stock->stock]);
            Db::commit();
            echo "买到第 $stock->stock 个!<br/>";
        }else{
            Db::rollback();
            echo '缺货<br/>';
        }
    }

测压命令

ab -n 260 -c 26 http://192.168.1.188:8042/index/test/test29

验证MySQL乐观锁与悲观锁并发情况

测压结果分析:90%的请求,都可以在1秒内完成。在库存充足情况下测试结果数据符合预期,库存不足时,ab测压工具经常报错(apr_socket_recv: 远程主机强迫关闭了一个现有的连接。 (730054))原因未知;

总结,正常情况下,还是悲观锁抗压

相关标签: 悲观锁 乐观锁