PHP高并发优化处理——redis层面详细步骤(php用redis 实现秒杀功能)

网友投稿 342 2022-06-17


php层面如何优化高并发?

redis层面:

(1)利用redis加锁机制处理setnx key value:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是SET if Not eXists的简写。

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

{

$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('领取失败,请查看网络连接');

}

}

}

}

暂且就先到到这里,欢迎拍砖!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:TP5 paginate()分页后给结果集追加字段和数据(tp53突变是什么意思)
下一篇:常用的PHP开发框架,为什么都喜欢用第七个?(php有框架吗)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~