• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

laravel+Redis简单实现队列通过压力测试的高并发处理

php 搞代码 4年前 (2022-01-21) 22次浏览 已收录 0个评论

这篇文章主要介绍了关于laravel+Redis简单实现队列通过压力测试的高并发处理 ,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

秒杀活动

在一般的网络商城中我们会经常接触到一些高并发的业务状况,例如我们常见的秒杀抢购等活动,

在这些业务中我们经常需要处理一些关于请求信息过滤以及商品库存的问题。

在请求中比较常见的状况是同一用户发出多次请求或者包含恶意的攻击,以及一些订单的复购等情况。

而在库存方面则需要考虑超卖这种状况。

下面我们来模拟一个简单可用的并发处理。

直接上代码

代码的流程

1.模拟用户请求,将用户写入redis队列中

2.从用户中取出一个请求信息进行处理(可以在这个步骤做更多的处理,请求过滤,订单复购等)

3.用户下单(支付等),减少库存。下面使用了两种方式进行了处理,一种使用了Redis中单线程原子操作的特性使程序一直线性操作从而保持了数据的一致

另外一种是用了事务进行操作,可以根据业务进行调整,这里就不一一描述了。

实际的业务状况更为复杂,但更多的是出于对基础思路的拓展。

<?phpnamespace App\Http\Controllers\SecKill;use App\Http\Controllers\Controller;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Redis;class SecKillControllers extends Controller {    public function SecKillTest() {     ///在此之前我们已经将一千过用户写入了redis中了        $num = Redis::lpop('user_list');     ///取出一个用户     ///     ///一些对请求的处理     ///        if (!is_null($num)) {       ///将需要秒杀的商品放入队列中            $this->AddGoodToRedis(1);       ///需要注意的是我们如果写的是秒杀活动的话,需要做进一步的处理,例如设置商品队列的缓存等方式,这里就实现了       ///下订单减库存            $this->GetGood(1,$num);        }    }    public function DoLog($log) {        file_put_contents("test.txt", $log . '\r\n', FILE_APPEND);    }    /**     * 重点在于Redis中存储数据的单线程的原子性,!!!无论多少请求同时执行这个方法,依然是依次执行的!!!!!     * 这种方式性能较高,并且确保了对数据库的单一操作,但容错率极低,一旦出现未可预知的错误会导致数据混乱;     */    public function GetGood($id,$user_id) {        $good = \App\Goods::find($id);        if (is_null($good)) {            $this->DoLog("商品不存在");            return 'error';        }        ///去除一个库存        $num = Redis::lpop('good_list');        ///判断取出库存是否成功        if (!$num) {            $this->DoLog("取出库存失败");            return 'error';        } else {            ///创建订单            $order = new \App\Order();            $order->good_id = $good->good_id;            $order->user_id = $user_id;            $order->save();            $ok = DB::table('Goods')                    ->where('good_id', $good->good_id)                    ->decrement('good_left', $num);            if (!$ok) {                $this->DoLog("库存减少失败");                return;            }            echo '下单成功';        }    }    public function AddUserToRedis() {        $user_count = 1000;        for ($i = 0; $i < $user_count; $i++) {            try {                Redis::lpush('user_list', rand(1, 10000));            } catch (Exception $e) {                echo $e->getMessage();            }        }        $user_num = Redis::llen('user_list');        dd($user_num);    }    public function AddGoodToRedis($id) {        $good = \App\Goods::find($id);        if ($good == null) {            $this->DoLog("商品不存在");            return;        }        ///获取当前redis中的库存。        $left = Redis::llen('good_list');        ///获取到当前实际存在的库存,库存减去Redis中剩余的数量。        $count = $good->good_left - $left;        //        dd($good->good_left);        ///将实际库存添加到Redis中        for ($i = 0; $i < $count; $i++) {            Redis::lpush('good_list', 1);        }        echo Redis::llen('good_list');    }    public function getGood4Mysql($id) {        DB::beginTransaction();        ///开启事务对库存以及下单进行处理        try {            ///创建订单            $order = new \App\Order();            $order->good_id = $good->good_id;            $order->user_id = rand(1, 1000);            $order->save();            $good = DB::table("goods")->where(['goods_id' => $id])->sharedLock()->first();            //对商品表进行加锁(悲观锁)            if ($good->good_left) {                $ok = DB::table('Goods')                        ->where('good_id', $good->good_id)                        ->decrement('good_left', $num);                if ($ok) {                    // 提交事务                    DB::commit();                    echo'下单成功';                } else {                    $this->DoLog("库存减少失败");                }            } else {                $this->DoLog("库存剩余为空");            }            DB::rollBack();            return 'error';        } catch (Exception $e) {            // 出错回滚数据            DB::rollBack();            return &#39<em>¥本文来%源[email protected]搞@^&代*@码)网5</em><strong>搞gaodaima代码</strong>;error';            //执行其他操作        }    }}

AB测试


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:laravel+Redis简单实现队列通过压力测试的高并发处理

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址