記錄一次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表發現商品並沒有超賣現象,日志表成功記錄所以搶購成功或者搶購失敗的日志。

還是有不懂的地方總之能 自己動手寫一遍 收益良多~~

 小白一枚 不喜勿噴~~如果我說錯了請指教,如果覺得蠢的話就蠢唄 哈哈哈

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM