侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

php+redis实现商城秒杀功能

Redis  /  管理员 发布于 5年前   361

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

 '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();    $goods_id = I("goods_id",'0','intval');       if($goods_id){      $this->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如下:

/**  * 访问产品前先将当前产品库存队列  * @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());    $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一个库存队列,如果在就抛出,):

/**   * 抢购商品前处理当前会员是否进入队列   * @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 = $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){      // 判断用户是否已在队列      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 = $this->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至此全部完成如下图:

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

您可能感兴趣的文章:

  • php+redis消息队列实现抢购功能
  • php结合redis实现高并发下的抢购、秒杀功能的实例
  • PHP实现Redis单据锁以及防止并发重复写入
  • PHP使用Redis实现防止大并发下二次写入的方法
  • PHP商品秒杀问题解决方案实例详解【mysql与redis】
  • yii框架redis结合php实现秒杀效果(实例代码)
  • php和redis实现秒杀活动的流程
  • php+redis实现消息队列功能示例
  • PHP+redis实现的限制抢购防止商品超发功能详解


  • 上一条:
    PHP基于redis计数器类定义与用法示例
    下一条:
    php+redis消息队列实现抢购功能
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在Redis中能实现的功能、常见应用介绍(0个评论)
    • 2024年Redis面试题之一(0个评论)
    • 在redis缓存常见出错及解决方案(0个评论)
    • 在redis中三种特殊数据类型:地理位置、基数(cardinality)估计、位图(Bitmap)使用场景介绍浅析(2个评论)
    • Redis 删除 key用 del 和 unlink 有啥区别?(1个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-12
    • 2020-03
    • 2020-05
    • 2021-04
    • 2022-03
    • 2022-05
    • 2022-08
    • 2023-02
    • 2023-04
    • 2023-07
    • 2024-01
    • 2024-02
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客