php+redis实现商城秒杀功能

好久没来整理文章了,闲了没事写篇文章记录下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;"> '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:

connect(C("REDIS_HOST"),C("REDIS_PORT")); return $redis; }

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']; }

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("当前产品已经秒杀完!"); }

}

接下来要做的就是用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="https://www.f2er.com/tag/yonghu/" target="_blank" class="keywords">用户</a>是否已在队列
  if (!$redis->hGet("{$this->user_queue_key}",$this->user_id)) {
    // 插入抢购<a href="https://www.f2er.com/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" => "系统繁忙,请重试!"));
}

}

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

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队列已释放!");      
 }

}

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

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

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

相关文章

Hessian开源的远程通讯,采用二进制 RPC的协议,基于 HTTP 传输。可以实现PHP调用Java,Python,C#等多语...
初识Mongodb的一些总结,在Mac Os X下真实搭建mongodb环境,以及分享个Mongodb管理工具,学习期间一些总结...
边看边操作,这样才能记得牢,实践是检验真理的唯一标准.光看不练假把式,光练不看傻把式,边看边练真把式....
在php中,结果输出一共有两种方式:echo和print,下面将对两种方式做一个比较。 echo与print的区别: (...
在安装好wampServer后,一直没有使用phpMyAdmin,今天用了一下,phpMyAdmin显示错误:The mbstring exte...
变量是用于存储数据的容器,与代数相似,可以给变量赋予某个确定的值(例如:$x=3)或者是赋予其它的变...