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

一、什么是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. 使用 Laravel 5.5+ 更好的来实现 404 响应

    译文首发于 使用 Laravel 5.5+ 更好的来实现 404 响应,转载请注明出处! Laravel 5.5.10 封装了两个有用的路由器方法,可以帮助我们为用户提供更好的 404 页面.现在,当 ...

  2. springboot实现拦截器

    你首先需要一个搭建好的springboot项目,具体怎么搭建我还没有相应的随笔可以交给你,可以自己上网上看一下,学习一下,之后我要是总结出来的话,这里面我会通知的 首先这个项目的目录结构是这样子的 首 ...

  3. J - Borg Maze

    J - Borg Maze 思路:bfs+最小生成树. #include<queue> #include<cstdio> #include<cstring> #in ...

  4. HDU 4686

    再不能直视这道题,换INT64就过了....... 同样可以使用矩阵的方法.构造1*5的 D[N],a[n],b[n],a[n]*b[n],1 接着你应该就会了. #include <iostr ...

  5. HDU 4365

    把涂色的格子按对称旋转至左上角. 当未涂色时,若要符合要求,则必须要求每一圈矩形都是上下左右对称的.注意是一圈的小矩形.对于N*N的阵,若最外层一圈的小矩形要符合要求,则(假设N%2==0)可以涂色的 ...

  6. 在ActivityA中关闭还有一个ActivityB

    1.对于简单的两个Activity public class A_activity extends Activity { public static A_activity _instance = nu ...

  7. 《SAS编程与数据挖掘商业案例》学习笔记之十五

    继续<SAS编程与数据挖掘商业案例>读书笔记,本次重点:输出控制 主要内容包含:log窗体输出控制.output窗体输出控制.ods输出控制 1.log窗体输出控制 将日志输出到外部文件 ...

  8. cocos2d-x 3.0 经常使用对象的创建方式

    cocos2d-x 3.0 中全部对象差点儿都能够用create函数来创建,其它的创建方式也是有create函数衍生. 以下来介绍下create函数创建一般对象的方法,省得开发中常常忘记啥的. 1.精 ...

  9. jenkins启动失败

    一:http://localhost:8080已经可以进了 二:修改端口 只是因为8080端口已经有程序占用了,需要修改端口号,但是在jenkins.xml文件中修改端口号,并不起作用. 解决方法是: ...

  10. bzoj1503: [NOI2004]郁闷的出纳员(伸展树)

    1503: [NOI2004]郁闷的出纳员 题目:传送门 题解: 修改操作一共不超过100 直接暴力在伸展树上修改 代码: #include<cstdio> #include<cst ...