记录一次Redis的运用 涉及商城秒杀 基于thinkphp5
https://blog.csdn.net/hao_mercury/article/details/79178735
基于以上链接大佬代码的实验 感谢~
首先在mysql创建数据库 商品表,抢购日志记录表,订单表;
并在goods插入一件商品 库存为50(件)
第二步下载Redis,网上教程挺多的不阐述,因为tp5自带的Redis拓展功能不够齐全所以使用外置的Redis
注意php的版本匹配适应的php_igbinary.dll和php_redis.dll;
https://windows.php.net/downloads/pecl/releases/igbinary/(php_igbinary.dll)
https://windows.php.net/downloads/pecl/releases/redis/(php_redis.dll)
记得去php.ini下配置!!
;php_redis extension=php_igbinary.dll extension=php_redis.dll
先导入外置Redis。
public function redis(){ $redis=new \Redis; //配置Redis本地ip和端口,因为我没设置Redis的密码所以不配置 //切记勿开启tp5自带的Redis $redis->connect('127.0.0.1',6379); return $redis; }
直接上代码吧 参考上面那位大佬的测试
<?php namespace app\index\controller; use think\Controller; use think\Db; class Index extends Controller{ public function redis(){ $redis=new \Redis; $redis->connect('127.0.0.1',6379); return $redis; } //秒杀的入口 public function index(){ $id="1";//设置商品id // 运行一次redisinit模拟入库Redis50次,运行一次屏蔽再进行压力测试 // $this->redisinit(); if(!$id) { //如果没有id为1的商品则记录一次失败日志状态为:0 return $this->insertlog(0); } // 接入Redis $redis=$this->redis(); // 移出Redis中goods_store队列中的第一个元素,详情参考Redis的lpop方法 $count=$redis->lpop('goods_store'); if(!$count){ // 如果goods_store队列中没有数据则抢购失败,记录一次失败日志(相当于没有库存抢购失败) $this->insertlog(0); return false; }else{ // 创建订单号 $orderrsn= $this->build_order_no(); // 随机创建抢购用户id $uid=rand(0,9999); //记录状态 $status= 1; // 查找goods表中的库存 $data=Db::table("goods")->field("count,amount")->where("id",$id)->find(); if(!$data){ // 没有则记录一次抢购失败日志 return $this->insertlog(0); } // goods商品存在库存时记录抢购成功,即生成订单一次 $result= Db::table("order")->insert(['order_sn'=>$orderrsn,'user_id'=>$uid,'goods_id'=>$id,'price'=>'50','status'=>$status,'addtime'=>'datetime']); // 生成订单一次后,goods商品的库存-1,setDec()方法详情参考tp5手册 $res=Db::table("goods")->where("id",$id)->setDec("count"); if($res){ // 下单成功的话记录一次抢购成功日志 状态为:1 $this->insertlog(1);} else{ // 失败时为:0 $this->insertlog(0); } } } //记录日志到log表的方法 public function insertlog($status){ $result= Db::execute('insert into log (addtime,status, count) values (:addtime,:status, :count)',['addtime'=>'datetime','status'=>$status,'count'=>'1']); return $result; } // 随机创建订单号方法 public function build_order_no(){ return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); } // 初始化Redis 模拟库存50个 public function redisinit(){ $store=50; $redis=$this->redis(); // 删除goods_store中一条缓存 $redis->del('goods_store'); // 返回goods_store的长度,此时为 0 $res=$redis->lLen('goods_store'); $count=$store-$res; for($i=0;$i<$count;$i++){ // 列表推进50个 模拟库存50 $redis->lPush('goods_store',1); } echo $redis->lLen('goods_store'); } }
进行压力测试,奇怪的是不能直接测试www.tp5.com这样的url 可是在后面加个 \ 确执行了......和上文的有出入 似乎是因为我tp5配置的原因 无法使用www.tp5.com\id\1这样的测试 所以在获取商品id的方面进行了改动
最后查询goods表发现商品并没有超卖现象,日志表成功记录所以抢购成功或者抢购失败的日志。
还是有不懂的地方总之能 自己动手写一遍 收益良多~~
小白一枚 不喜勿喷~~如果我说错了请指教,如果觉得蠢的话就蠢呗 哈哈哈