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: 

rush: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.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>是否已在队列
  if (!$re<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>->hGet("{$this->user_queue_key}",$this->user_id)) {
    // 插入抢购<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>信息
    $userinfo = array(
      "user_id" => $this->user_id,"create_time" => time()
    );        
    $re<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>->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("Re<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>队列已释放!");      
 }

}

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


服务器优化必备:深入了解PHP8底层开发原理
Golang的网络编程:如何快速构建高性能的网络应用?
Golang和其他编程语言的对比:为什么它的开发效率更高?
PHP8底层开发原理揭秘:如何利用新特性创建出色的Web应用
将字符重新排列以形成回文(如果可能)在C++中
掌握PHP8底层开发原理和新特性:创建高效可扩展的应用程序
服务器性能优化必学:掌握PHP8底层开发原理
PHP8新特性和底层开发原理详解:优化应用性能的终极指南
将 C/C++ 代码转换为汇编语言
深入研究PHP8底层开发原理:创建高效可扩展的应用程序
C++程序查找法向量和迹
PHP8底层开发原理实战指南:提升服务器效能
重排数组,使得当 i 为偶数时,arr[i] >= arr[j],当 i 为奇数时,arr[i] <= arr[j],其中 j < i,使用 C++ 语言实现
Golang的垃圾回收:为什么它可以减少开发人员的负担?
C++程序:将一个数组的所有元素复制到另一个数组中
Golang:构建智能系统的基石
为什么AI开发者应该关注Golang?
在C和C++中,逗号(comma)的用法是用来分隔表达式或语句
PHP8底层开发原理解析及新特性应用实例
利用PHP8底层开发原理解析新特性:如何构建出色的Web应用