php+redis实现商城秒杀功能
前端之家收集整理的这篇文章主要介绍了
php+redis实现商城秒杀功能,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_404_0@好久没来整理文章了,闲了没事写篇文章记录下PHP+redis实现商城秒杀功能。
@H_
404_0@1、安装redis,根据自己的
PHP版本安装对应的redis扩展(此步骤简单的描述一下)
@H_
404_0@1.1.安装
PHP_igbinary.dll,
PHP_redis.dll扩展此处需要注意你的
PHP版本如图:
<p style="text-align: center">

@H_
404_0@1.2.
PHP.ini
文件新增extension=
PHP_igbinary.dll;extension=
PHPredis.dll两处扩展
@H404_0@ok此处已经完成第一步redis环境搭建完成看看
PHPinfo
@H_
404_0@

@H_
4040@2、项目中实际使用redis
@H404_0@2.1.第一步配置redis参数如下,redis安装的默认端口为6379:
<div class="jb51code">
<pre class="brush:
PHP;">
<?php
/
数据库配置 /
return array(
'DATA_CACHE
PREFIX' => 'Redis',//缓存前缀
'DATA_CACHE_TYPE'=>'Redis',//默认动态缓存为Redis
'DATA_CACHE_TIMEOUT' => false,'REDIS_RW_SEPARATE' => true,//Redis读写分离 true 开启
'REDIS_HOST'=>'127.0.0.1',//redis服务器ip,多台用逗号隔开;读写分离开启时,第一台负责写,其它[
随机]负责读;
'REDIS_PORT'=>'6379',//端口号
'REDIS_TIMEOUT'=>'300',//超时时间
'REDIS_PERSISTENT'=>false,//是否长连接 false=短连接
'REDIS_AUTH'=>'',//AUTH认证密码
);
?>
@H_
404_0@2.2.实际
函数中使用redis:
connect(C("REDIS_HOST"),C("REDIS_PORT"));
return $redis;
}
@H_
404_0@2.3. 秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据
生成:
goods_id = $goods_id;
$this->user_queue_key = "goods_".$goods_id."_user";//当前商品队列的
用户情况
$this->goods_number_key = "goods".$goods_id;//当前商品的库存队列
}
$this->user_id = $this->user_id ? $this->user_id : $_SESSION['uid'];
}
@H_
404_0@2.4. 第二步就是关键所在,
用户在进入商品详情页前先将当前商品的库存进行队列存入redis如下:
goods_id;
$where['start_time'] = array("lt",time());
$where['end_time'] = array("gt",time());
$goods = M("goods")->where($where)->field('goods_num,start_time,end_time')->find();
!$goods && $this->error("当前秒杀已结束!");
if($goods['goods_num'] > $goods['order_num']){
$redis = $this->connectRedis();
$getUserRedis = $redis->hGetAll("{$this->user_queue_key}");
$gnRedis = $redis->llen("{$this->goods_number_key}");
/* 如果没有会员进来队列库存 */
if(!count($getUserRedis) && !$gnRedis){
for ($i = 0; $i < $goods['goods_num']; $i ++) {
$redis->lpush("{$this->goods_number_key}",1);
}
}
$resetRedis = $redis->llen("{$this->goods_number_key}");
if(!$resetRedis){
$this->error("系统繁忙,请稍后抢购!");
}
}else{
$this->error("当前产品已经秒杀完!");
}
}
@H_
404_0@接下来要做的就是用ajax来异步的处理
用户点击购买按钮进行符合条件的数据进入购买的排队队列(如果当前
用户没在当前产品
用户的队列就进入排队并且pop一个库存队列,如果在就抛出,):
user_id && $this->ajaxReturn(array("status" => "-1","msg" => "请先
登录"));
$model = M("flash_sale");
$where['goods_id'] = $this->goods_id;
$goods_info = $model->where($where)->find();
!$goods_info && $this->error("对不起当前商品不存在或已下架!");
/* redis 队列 */
$redis = $this->connectRedis();
/* 进入队列 */
$goods_number_key = $redis->llen("{$this->goods_number_key}");
if (!$redis->hGet("{$this->user_queue_key}",$this->user_id)) {
$goods_number_key = $redis->lpop("{$this->goods_number_key}");
}
if($goods_number_key){
// 判断<a href="/tag/yonghu/" target="_blank" class="keywords">用户</a>是否已在队列
if (!$redis->hGet("{$this->user_queue_key}",$this->user_id)) {
// 插入抢购<a href="/tag/yonghu/" target="_blank" class="keywords">用户</a>信息
$userinfo = array(
"user_id" => $this->user_id,"create_time" => time()
);
$redis->hSet("{$this->user_queue_key}",$this->user_id,serialize($userinfo));
$this->ajaxReturn(array("status" => "1"));
}else{
$modelCart = M("cart");
$condition['user_id'] = $this->user_id;
$condition['goods_id'] = $this->goods_id;
$condition['prom_type'] = 1;
$cartlist = $modelCart->where($condition)->count();
if($cartlist > 0){
$this->ajaxReturn(array("status" => "2"));
}else{
$this->ajaxReturn(array("status" => "1"));
}
}
}else{
$this->ajaxReturn(array("status" => "-1","msg" => "系统繁忙,请重试!"));
}
}
@H_
404_0@附加一个调试的
函数,
删除指定队列值:
connectRedis();
//$Rd = $redis->del("{$this->user_queue_key}");
$Rd = $redis->hDel("goods49",'
用户id'');
$a = $redis->hGet("goods_49_user",'
用户id');
if(!$a){
dump($a);
}
if($Rd == 0){
exit("Redis队列已释放!");
}
}
@H_
404_0@走到此处的时候秒杀的核心基本就完了,细节还需要自己在去完善,像购物车这边的处理还有订单的处理,好吧开始跑程序利用apache自身的ab可以进行简单的模拟并发测试如下:
@H_
404_0@

@H_
404_0@跑起来,我擦跑步起来redis没有任何反应,此时还少一步重要的步骤就是开启redis服务,请根据自己的系统下一个redisbin_x32或者redisbin_x64的redis服务管理工具,点击redis-server.exe,ok至此全部完成如下图:
@H_
404_0@

@H_
404_0@以上就是本文的全部
内容,希望对大家的学习有所帮助,也希望大家多多
支持编程之家。