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
2,项目中实际使用redis
2.1,第一步配置redis参数如下,redis安装的默认端口为6379:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?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:
1
2
3
4
5
6
7
8
9
10
11
|
/** * 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,秒杀的核心问题是在大并发的情况下不会超出库存的购买,这个就是处理的关键所以思路是第一步在秒杀类的先做一些基础的数据生成:
1
2
3
4
5
6
7
8
9
10
11
|
//现在初始化里面定义后边要使用的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如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/** * 访问产品前先将当前产品库存队列 * @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一个库存队列,如果在就抛出,):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/** * 抢购商品前处理当前会员是否进入队列 * @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" => "系统繁忙,请重试!" )); } } |
附加一个调试的函数,删除指定队列值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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至此全部完成如下图:
一个人静静坐在电脑面前写代码的感觉,那是什么感觉?那是武林高手闭关修炼的感觉。
thinkphp+redis实现秒杀功能(转)的更多相关文章
- thinkphp+redis实现秒杀功能
好久没来整理文章了,闲了没事写篇文章记录下php+redis实现商城秒杀功能. 1,安装redis,根据自己的php版本安装对应的redis扩展(此步骤简单的描述一下) 1.1,安装 php_igbi ...
- thinkphp+redis实现秒杀,缓存等功能
秒杀是商城常见功能 php+redis是最常见的秒杀功能 1,安装redis,根据自己的php版本安装对应的redis扩展 首先查看phpinfo();php环境信息 2,下载redis https ...
- php结合redis实现秒杀功能
<?php 第一种,简单实现 $conn=mysql_connect("localhost","big","123456"); if( ...
- 电商项目中使用Redis实现秒杀功能
参与过抢购活动就知道,很明显的一点是商即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了. 实现原理:list双向链表 使用redis队列,因为pop操作是原子的,即使有很多用户 ...
- php+redis实现电商秒杀功能
这一次总结和分享用Redis实现分布式锁来完成电商的秒杀功能.先扯点个人观点,之前我看了一篇博文说博客园的文章大部分都是分享代码,博文里强调说分享思路比分享代码更重要(貌似大概是这个意思,若有误请谅解 ...
- Redis事务和实现秒杀功能的实现
今天带着学生学习了Redis的事务功能,Redis的事务与传统的关系型数据库(如MySQL)有所不同,Redis的事务不能回滚. Redis中使用multi.exec.discard.watch.un ...
- Redis分布式锁实现简单秒杀功能
这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...
- spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)
一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...
- 秒杀功能压测 jmeter--------重要!!!
线程组里面有三个接口请求,依次为:显示商品列表.登录秒杀平台账户.进行秒杀 对线程组用5000个线程循环10次 设置一下默认配置,之后就不用反复填写了 设置配置文件这个具体功能就是读text文件并且设 ...
随机推荐
- 利用JsonSchema校验json数据内容的合规性(转)
原文地址:Json schema 背景: 复杂的AJAX应用程序可以与数百个不同的JSON服务进行交互,因此,引入对客户端验证的需求. 在处理校验问题方面有着很多的工具,但是通常可以将它们归为以下几类 ...
- 二十二、Spring MVC与Structs2的区别总结
一.框架的入口 1.Structs2采用Filter(StructsPrepartAndExecuteFilter)来进行实现. 2.SpringMVC采用Servlet(DispatcherServ ...
- Analytic Functions in Oracle
Contents Overview and IntroductionHow Analytic Functions WorkThe SyntaxExamplesCalculate a running T ...
- python中的包
- 默认五笔输入法qq
默认五笔输入法 1● 五笔设置 2● 语言设置 Success
- matlab server mapreduce
>> Z = server.rpc('zeros', 2, 3);>> Z = [2x3 double] [2x3 double] >> Z{1}ans = 0 0 ...
- zabbix3.4.7监控linux进程
利用zabbix proc.num方法监控Linux服务进程 proc.num[<name>,<user>,<state>,<cmdline>] 监控用 ...
- Linux第三周作业
1.三个法宝 ①存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: ②函数调用堆栈,堆栈完成了计算机的基本功能:函数的参数传递机制和局部变量存取 : ③中断,多道程序操作系统的基点,没有中断机制 ...
- laravel模型关联:
一对一hasOne(用户-手机号) 一对多has Many(文章-评论) 一对多反向belongsTo(评论-文章) 多对多belongsToMany(用户-角色) 远层一对多hasManyThrou ...
- 通过改变unity中物体的alpha值实现若隐若现的效果
RawImage logo = mainLogo.transform.FindChild("back/headBack/Logo").GetComponent<RawImag ...