手机版

php处理对快照功能的高并发请�

时间:2021-09-01 来源:互联网 编辑:宝哥软件园 浏览:

本文以抓人和杀人为例。描述如何确保高并发下的数据正确。在高并发请求下,参数容易出现两个问题。1.数据错误导致产品超卖。2.频繁的数据库操作会导致性能下降。

测试环境

windows 7 Apache 2 . 4 . 9 PHP 5 . 5 . 12 PHP框架yii2.0工具apache bench (apache自带高并发请求工具)。

常用治疗方法

代码的想法可以从控制器上看到。先查商品库存。如果库存大于0,库存将减少1。同时,将生成订单并输入买方数据。

//通用代码处理高并发公共函数操作正常(){//查询库存$ stock=goods :3360 find()-select(' stock ')-其中([' goods _ id '=100001])-asar ray()-one();//判断商品是否有库存如果($stock['stock']0) {//Stock减一goods : updateall counters([' Stock '=-1],[' goods _ id '=100001]);//生产订单(对于另一个函数,暂时随机赋值)$ order=$ this-build _ order();//将信息钉入存储$ model=new highlight();$ model-order _ id=$ order;$ model-goods _ name=' kill goods ';$ model-buy _ time=date(' Y-m-d h : I :s ',time());$ model-mircrotime=micro time(true);If($model-save()===false){ echo '未能抢购!}else{ echo '恭喜,订单'。$订单。“抢购成功”;} }else{ echo '已被抢购一空!}}商品库存设置为20后,通过ab配置并发请求200。

a B- n200-c200 http///localhost/highlight/normal执行结果发现库存变为负数,商品超卖。

原因很简单,在高并发请求下。在生产订单和库存减少之前,会先查询库存结果。

优化1:修改库存数据类型

第一种优化方法从数据库开始。由于查询结果不准确,我会在库存减少上作弊。将库存的数据类型更改为无符号(不允许负值)。

代码还是和上面类似,只做一个库存减少1的判断。避免报告错误。

公共函数action normal(){//查询库存$ stock=goods :3360 find()-select(' stock ')-其中([' goods _ id '=100001])-asar ray()-one();//确定商品是否有库存if($ stock[' stock ']0){//Inventory减一if(goods : updateall counters([' stock '=-1],[' goods _ id '=100001])===false){ Echo '已经;返回false}//生产订单(另一个函数,临时赋一个随机值)$ order=$ this-build _ order();//将信息钉入存储$ model=new highlight();$ model-order _ id=$ order;$ model-goods _ name=' kill goods ';$ model-buy _ time=date(' Y-m-d h : I :s ',time());$ model-mircrotime=micro time(true);如果($model-save()===false){ echo '未能抢购!}else{ echo '恭喜,订单'。$订单。“抢购成功”;} } else { echo }已被抢购一空!}}这次200的并发是一样的,进行结果发现。如果数据正确,就不会出现超卖。这个想法其实比较简单。因为库存不能为负,当库存等于0时,如果有任何值进入,将报告错误。请求被终止。

这种优化方法可以避免商品超卖。但另一方面,请求仍然给数据库带来压力。如果多个函数使用该数据库,将导致严重的性能下降。

优化2: redis

使用redis列表类型pop的原子性。在操作数据库之前进行验证。商品售罄后,不允许继续数据库操作。

//redis list高并发测试公共函数action redis(){ $ redis=\ yii :3360 $ app-redis;//$redis-lpush('mytest ',1);$ order=$ this-build _ order();//echo $ order;死去;//echo $ redis-llen(' my test ');$ reg=$ redis-lpop(' my test ');if(!$reg) {echo '白痴!“它被抢了!”;返回false} $ redis-close();$ model=new Health();$ model-order _ id=$ order;$ model-goods _ name=' kill goods ';$ model-buy _ time=date(' Y-m-d h : I :s ',time());$ model-mircrotime=micro time(true);If($model-save()===false){ echo '未能抢购!}else{ echo '恭喜,订单'。$订单。“抢购成功”;} }//将公共函数actioninsertgoods(){ $ count=yii :3360 $ app-request-get(' count ',0)添加到redis如果(空的($count)) {echo '大哥,你还没告诉我需要上架多少货!返回false} $ redis=\ yii : $ app-redis;for($ I=0;$ i $计数;$i ) { $redis-lpush('mytest ',1);}回声“已成功添加”。$redis-llen('mytest ')。物品。$ redis-close();}这段代码,我写了两个方法。第一种方法是二杀码,第二种方法是设置二杀货的数量。为了方便测试,我在这里简单处理一下。

通过测试,数据库产生的订单数量正常,没有问题。同时避免了数据库请求导致的性能下降问题。同时内存数据库redis的查询速度也比mysql快很多。

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

版权声明:php处理对快照功能的高并发请�是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。