PHP+Redis实现高并发应用商城秒杀功能

开发的电子商务平台也很多了,刚好有时间就整理一下巩固加深理解

1、安装redis,根据自己的php版本安装对应的redis扩展(此步骤简单的描述一下)

1.1.安装php_igbinary.dll,php_redis.dll扩展此处需要注意你的php版本如图:

1.2.php.ini文件新增extension=php_igbinary.dll;extension=php_redis.dll两处扩展

ok此处已经完成第一步redis环境搭建完成看看phpinfo

2、项目中实际使用redis

2.1.第一步配置redis参数如下,redis安装的默认端口为6379:

<?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认证密码 ); ?>

2.2.实际函数中使用redis:

/**
* redis连接
* @access private
* @return resource
* @author bieanju
*/
private function connectRedis(){
$redis=new \Redis();
$redis->connect(C(“REDIS_HOST”),C(“REDIS_PORT”));
return $redis;
}

2.3. 秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据生成:

//现在初始化里面定义后边要使用的redis参数
public function _initialize(){
parent::_initialize();
g o o d s i d = I ( &quot; g o o d s i d &quot; , ′ 0 ′ , ′ i n t v a l ′ ) ; i f ( goods_id = I(&quot;goods_id&quot;,&#x27;0&#x27;,&#x27;intval&#x27;); if( goodsid=I("goodsid",0,intval);if(goods_id){
$this->goods_id = $goods_id;
t h i s − &gt; u s e r q u e u e k e y = &quot; g o o d s &quot; . this-&gt;user_queue_key = &quot;goods_&quot;. this>userqueuekey="goods".goods_id."_user";//当前商品队列的用户情况
t h i s − &gt; g o o d s n u m b e r k e y = &quot; g o o d s &quot; . this-&gt;goods_number_key = &quot;goods&quot;. this>goodsnumberkey="goods".goods_id;//当前商品的库存队列
}
$this->user_id = $this->user_id ? $this->user_id : $_SESSION[‘uid’];
}

2.4. 第二步就是关键所在,用户在进入商品详情页前先将当前商品的库存进行队列存入redis如下:

/**

  • 访问产品前先将当前产品库存队列
  • @access public
  • @author bieanju
    /
    public function _before_detail(){
    $where[‘goods_id’] = $this->goods_id;
    $where[‘start_time’] = array(“lt”,time());
    $where[‘end_time’] = array(“gt”,time());
    g o o d s = M ( &quot; g o o d s &quot; ) − &gt; w h e r e ( goods = M(&quot;goods&quot;)-&gt;where( goods=M("goods")>where(where)->field(‘goods_num,start_time,end_time’)->find();
    !$goods && t h i s − &gt; e r r o r ( &quot; 当 前 秒 杀 已 结 束 ! &quot; ) ; i f ( this-&gt;error(&quot;当前秒杀已结束!&quot;); if( this>error("");if(goods[‘goods_num’] > $goods[‘order_num’]){
    $redis = $this->connectRedis();
    $getUserRedis = KaTeX parse error: Expected '}', got 'EOF' at end of input: …dis->hGetAll("{this->user_queue_key}");
    $gnRedis = KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->llen("{this->goods_number_key}");
    /
    如果没有会员进来队列库存 */
    if(!count(KaTeX parse error: Expected 'EOF', got '&' at position 15: getUserRedis) &̲& !gnRedis){
    for ($i = 0; $i < $goods[‘goods_num’]; $i ++) {
    KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->lpush("{this->goods_number_key}", 1);
    }
    }
    $resetRedis = KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->llen("{this->goods_number_key}");
    if(!$resetRedis){
    $this->error(“系统繁忙,请稍后抢购!”);
    }
    }else{
    $this->error(“当前产品已经秒杀完!”);
    }

}

接下来要做的就是用ajax来异步的处理用户点击购买按钮进行符合条件的数据进入购买的排队队列(如果当前用户没在当前产品用户的队列就进入排队并且pop一个库存队列,如果在就抛出,):

/**

  • 抢购商品前处理当前会员是否进入队列
  • @access public
  • @author bieanju
    /
    public function goods_number_queue(){
    !$this->user_id && $this->ajaxReturn(array(“status” => “-1”,“msg” => “请先登录”));
    $model = M(“flash_sale”);
    $where[‘goods_id’] = $this->goods_id;
    $goods_info = m o d e l − &gt; w h e r e ( model-&gt;where( model>where(where)->find();
    !$goods_info && $this->error(“对不起当前商品不存在或已下架!”);
    /
    redis 队列 /
    $redis = $this->connectRedis();
    /
    进入队列 */
    $goods_number_key = KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->llen("{this->goods_number_key}");
    if (!KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->hGet("{this->user_queue_key}", $this->user_id)) {
    $goods_number_key = KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->lpop("{this->goods_number_key}");
    }
if($goods_number_key){
  // 判断用户是否已在队列
  if (!$redis->hGet("{$this->user_queue_key}", $this->user_id)) {
    // 插入抢购用户信息
    $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" => "系统繁忙,请重试!"));
}

}

附加一个调试的函数,删除指定队列值:

public function clearRedis(){
set_time_limit(0);
$redis = t h i s − &gt; c o n n e c t R e d i s ( ) ; / / this-&gt;connectRedis(); // this>connectRedis();//Rd = KaTeX parse error: Expected '}', got 'EOF' at end of input: redis->del("{this->user_queue_key}");
$Rd = $redis->hDel(“goods49”,‘用户id’’);
$a = r e d i s − &gt; h G e t ( &quot; g o o d s 4 9 u s e r &quot; , ′ 用 户 i d ′ ) ; i f ( ! redis-&gt;hGet(&quot;goods_49_user&quot;, &#x27;用户id&#x27;); if(! redis>hGet("goods49user",id);if(!a){
dump($a);
}

 if($Rd == 0){
   exit("Redis队列已释放!");      
 }

}

走到此处的时候秒杀的核心基本就完了,细节还需要自己在去完善,像购物车这边的处理还有订单的处理,好吧开始跑程序利用apache自身的ab可以进行简单的模拟并发测试如下:

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

转载地址:http://www.jb51.net/article/134662.htm

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值