记录一次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表发现商品并没有超卖现象,日志表成功记录所以抢购成功或者抢购失败的日志。

还是有不懂的地方总之能 自己动手写一遍 收益良多~~

 小白一枚 不喜勿喷~~如果我说错了请指教,如果觉得蠢的话就蠢呗 哈哈哈

 

posted @ 2018-12-26 11:18  senya冉  阅读(1284)  评论(0编辑  收藏  举报