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表发现商品并没有超卖现象,日志表成功记录所以抢购成功或者抢购失败的日志。
还是有不懂的地方总之能 自己动手写一遍 收益良多~~
小白一枚 不喜勿喷~~如果我说错了请指教,如果觉得蠢的话就蠢呗 哈哈哈