在实际的开发过程中我们遇到过各种各样的活动,但像用户流量较大的平台就需要考虑高并发的问题,但是如何去解决呢?我总结了几种解决方案,欢迎大家指正!

一、什么是PV/UV/QPS?

PV:页面访问量,即PageView,用户每次对网站的访问均被记录,用户对同一页面的多次访问,访问量累计。(说白了就是用户的点击次数)
UV:独立访问用户数:即UniqueVisitor,访问网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只被计算一次。(说白了就是每天访问的用户数)
QPS: (每秒查询率) : 每秒钟请求或者查询的数量,在互联网领域,指每秒响应请求数(指HTTP请求)

二、php层面如何优化高并发?
1.redis层面:
(1)利用redis加锁机制处理setnx key value:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是SET if Not eXists的简写。



<?php class Lock
{
private static $_instance ;
private $_redis;
private function __construct()
{
$this->_redis = new Redis();
$this->_redis ->connect('127.0.0.1');
}
public static function getInstance()
{
if(self::$_instance instanceof self)
{
return self::$_instance;
}
return self::$_instance = new self();
}
/**
* @function 加锁
* @param $key 锁名称
* @param $expTime 过期时间
*/
public function set($key,$expTime)
{
//初步加锁
$isLock = $this->_redis->setnx($key,time()+$expTime);
if($isLock)
{
return true;
}
else
{
//加锁失败的情况下。判断锁是否已经存在,如果锁存在且已经过期,那么删除锁。进行重新加锁
$val = $this->_redis->get($key);
if($val&&$val<time())
{
$this->del($key);
}
return $this->_redis->setnx($key,time()+$expTime);
}
}
/**
* @param $key 解锁
*/
public function del($key)
{
$this->_redis->del($key);
}
} $pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'root');
$lockObj = Lock::getInstance(); //单例模式
//判断是能加锁成功
if($lock = $lockObj->set('storage',10))
{
$sql="select `number` from storage where id=1 limit 1";
$res = $pdo->query($sql)->fetch();
$number = $res['number'];
if($number>0)
{
$sql ="insert into `order` VALUES (null,$number)"; $order_id = $pdo->query($sql);
if($order_id)
{ $sql="update storage set `number`=`number`-1 WHERE id=1";
$pdo->query($sql);
}
}
//解锁
$lockObj->del('storage'); }
else
{
//加锁不成功执行其他操作。
}
?>

(2)利用reids消息队列处理高并发:队列是按先进先出的顺序来执行,需要用到 lpop、rpush、llen等方法


/**
*优惠券redis入库
**/
public function reload_quan(){
$yhq_dom = Yhq_user_relation::i();
$redis = Redis::i('redis');
$redis->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE );
for ($i=0;$i<100;$i++){
$date_time = date('Y-m-d H:i:s',time());
$res = $yhq_dom->add([
'hd_id' => 3,
'yhq_id'=> 19,
'name' => '满58减20',
'create_time' => $date_time,
'price' => 58,
'yuanbao' => 20
]);
if (!$res){
$this->_error('添加第'.$i.'张优惠券时失败');
}
//在redis中存入数据
$redis->rPush('yhq_relation',"{$i}");
}
$redis->expire('yhq_relation',1860);
$this->_success('','库内添加优惠券成功');
}
/**
*领取优惠券
**/
public function get_quan(){
$redis = Redis::i('redis');
$redis->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE );
$start_time = date('Y-m-d 00:00:00',time());
$stop_time = date('Y-m-d 23:59:59',time());
//判断是否在抢购时间内
//$start_string = mktime(12,0,0,date('m'),date('d')-date('w')+5,date('Y'));
//$stop_string = mktime(23,59,59,date('m'),date('d')-date('w')+5,date('Y'));
//$now_time = time();
//if ($now_time<$start_string || $now_time>$stop_string){
// $this->_error('抢券时间未到,请稍后再来~');
//}
$len = $redis->lLen('yhq_relation');
if ($len<1){
$this->_error('优惠券已经抢光啦~');
}else{
//领取优惠券时判断用户是否真正领取
$user_id = $this->_user_info()['accid'];
$yhq_dom = Yhq_user_relation::i();
$where = [
'accid' => $user_id,
'hd_id' => 3,
'yhq_id'=>19,
'create_time' => [
'between' => [$start_time,$stop_time]
]
];
$result = $yhq_dom->where($where)->find();
if($result){
$this->_error('对不起,您已经领取过了哦~');
}else{
//用户领取优惠券
$expire_time = date('Y-m-d H:i:s',(time()+259200));
$sql = "select id from yhq_user_relation where hd_id = 3 and yhq_id=19 and create_time between '$start_time' and '$stop_time' and accid is NULL ORDER by create_time ASC ";
$update_id = $yhq_dom->query($sql)[0]['id'];
//双重判断是否已经领取完毕
if (!$update_id){
$this->_error('优惠券已经抢光了哦~');
}
$redis->lPop('yhq_relation');
$res = $yhq_dom->update("id={$update_id}",['accid'=>$user_id,'expire_time'=>$expire_time]);
if ($res){
$this->_success('','领取成功');
}else{
$this->_error('领取失败,请查看网络连接');
}
}
}
}

2.数据库层面(暂时没有总结好)

原文地址:https://segmentfault.com/a/1190000016573896

[php]如何做到高并发优化的更多相关文章

  1. 性能调优之MYSQL高并发优化

    性能调优之MYSQL高并发优化   一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之 ...

  2. 【JAVA】高并发优化细节点

    高并发优化细节点: 微服务化 如何发现系统瓶颈?   如何高效利用有限内存: 使用基本类型 使用数组,不用集合 自定义map与数据结构   Integer—>int, Set<Intege ...

  3. Java高并发秒杀API之高并发优化

    ---恢复内容开始--- 第1章 秒杀系统高并发优化分析   1.为什么要单独获得系统时间 访问cdn这些静态资源不用请求系统服务器 而CDN上没有系统时间,需要单独获取,获取系统时间不用优化,只是n ...

  4. Apache Tomcat 8.5 安全配置与高并发优化

    通常我们在生产环境中,Tomcat的默认配置显然不能满足我们的产品需求,所以很多时候都需要对Tomcat的配置进行调优,以下综合我自己的经验来配置 Tomcat 安全与优化情况,如果你有更好的方案,请 ...

  5. MySQL MyISAM/InnoDB高并发优化经验

    最近做的一个应用,功能要求非常简单,就是 key/value 形式的存储,简单的 INSERT/SELECT,没有任何复杂查询,唯一的问题是量非常大,如果目前投入使用,初期的单表 insert 频率约 ...

  6. 04 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之高并发优化

    Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 关于并发 并发性上不去是因为当多个线程同时访问一行数 ...

  7. SSM实战——秒杀系统之高并发优化

    一:高并发点 高并发出现在秒杀详情页,主要可能出现高并发问题的地方有:秒杀地址暴露.执行秒杀操作. 二:静态资源访问(页面)优化——CDN CDN,内容分发网络.我们把静态的资源(html/css/j ...

  8. nginx php-fpm 高并发优化

    PHP-php-fpm配置优化 前言: 1.少安装PHP模块, 费内存 2.调高linux内核打开文件数量,可以使用这些命令(必须是root帐号)(我是修改/etc/rc.local,加入ulimit ...

  9. SSM(Spring+SpringMVC+MyBatis)高并发优化思路

    SSM(Spring+SpringMVC+MyBatis)框架集由Spring.MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容).常作为数据源较简单的web项目的框架 ...

随机推荐

  1. Linux 基础入门一

    操作系统1.简介OS: Operating System,通用目的的软件程序操作系统的内核(kernel):  操作系统其实也是一组程序.这组程序的重点在于管理计算机的所有活动及驱动系统中的所有硬件: ...

  2. 出现$ref的原因及解决方案

    $ref的产生原因 (1)重复引用:一个集合/对象中的多个元素/属性都引用了同一个对象 (2)循环引用:集合/对象中的多个元素/属性在相互引用导致循环 针对fastjson的处理 fastjson作为 ...

  3. uni-app 之验证码

    手机APP---验证码 最近公司在开发手机APP,app避不可免的就是登录了,emmmm 登录验证码那必须的是有的,我们公司发给我们的图片是酱紫的~~ 这个要求大家应该都能看懂,做这个手机号啊,验证码 ...

  4. soapui测试接口使用步骤

    1.新建项目 2. 定义接口 url输入接口 3.新建测试集 选择项目,右键 4.在测试集下新建测试用例 5.在测试步骤中导入要测试的请求 6.run

  5. 俄罗斯方块c/c++语言代码

    /*******************************/ /******Writer: GJ *******/ /******Language: C *******/ /******Date ...

  6. C#基础概念 代码样例

    C# int与string一起操作时注意 1 int a1= 1; 2 string a2= "2"; 3 Console.WriteLine(a1+a2); 4 Console. ...

  7. rabbitMQ学习笔记(三) 消息确认与公平调度消费者

    从本节开始称Sender为生产者 , Recv为消费者   一.消息确认 为了确保消息一定被消费者处理,rabbitMQ提供了消息确认功能,就是在消费者处理完任务之后,就给服务器一个回馈,服务器就会将 ...

  8. grpc mvn protobuf:compile 过程

    grpc mvn protobuf:compile 过程 编写代码之后,直接使用 mvn protobuf:compile会报错,木有protoc.exe文件: 可以使用Terminal输入mvn命令 ...

  9. RabbitMQ从入门到精通

    RabbitMQ从入门到精通 学习了:http://blog.csdn.net/column/details/rabbitmq.html RabbitMQ是AMQP(advanced message ...

  10. oracle 有个xe版本

    oracle 有个xe版本 学习了:http://blog.csdn.net/angiexia/article/details/8615771