详解thinkphp+redis+队列的实现代码
2021/5/2 2:25:31
本文主要是介绍详解thinkphp+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
项目中实际使用redis
2.1,第一步配置redis参数如下,redis安装的默认端口为6379:
1234567891011121314 | <?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:
1234567891011 | /** * 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,秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据生成:
1234567891011 | //现在初始化里面定义后边要使用的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如下:
123456789101112131415161718192021222324252627282930 | /** * 访问产品前先将当前产品库存队列 * @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一个库存队列,如果在就抛出,):
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 | /** * 抢购商品前处理当前会员是否进入队列 * @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" => "系统繁忙,请重试!" )); } } |
附加一个调试的函数,删除指定队列值:
1234567891011121314 | 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队列已释放!" ); } } |
这篇关于详解thinkphp+redis+队列的实现代码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-19php8的协程和hyperf的协程有什么区别?-icode9专业技术文章分享
- 2024-12-19php8 的fiber是什么?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-11-29使用PHP 将ETH账户的资产汇集到一个账户
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享