<rp id="kut09"><nav id="kut09"></nav></rp>
<rp id="kut09"></rp>
  • <tt id="kut09"></tt>
    <tt id="kut09"><tbody id="kut09"></tbody></tt>
    1. <u id="kut09"></u>
    2. <tt id="kut09"><noscript id="kut09"></noscript></tt>
    3. Thinkphp5+Redis實現商品秒殺代碼實例講解

       更新時間:2020年12月29日 16:54:56   作者:下頁、再停留  
      這篇文章主要介紹了Thinkphp5+Redis實現商品秒殺代碼實例講解,代碼和步驟講解的很清楚,有需要的同學可以借鑒參考下

      環境:wamp,redis

      要求:安裝WAMP,Redis,以及為PHP安裝Redis擴展

      秒殺功能大致思路:獲取緩存列表的長度,如果長度(llen)等于0,就停止秒殺,即秒殺失敗,如果長度大于0,則繼續運行,先從緩存中移除一個元素(lpop),再進行數據庫操作(添加訂單表,商品庫存數量減一),如果再進一個人秒殺,就再走一遍流程,循環往復。

      一、安裝Redis擴展

      1.查看PHP版本信息

      打開phpinfo.php,查看PHP版本,我的是PHP7.3.4,還有一個需要注意Architecture x64

      2.下載擴展文件

      https://pecl.php.net/package/redis

      https://pecl.php.net/package/igbinary

      根據自己環境,選擇合適的版本

      3.解壓

      解壓下載的壓縮包,并把php_redis.dll、php_redis.pdb和php_igbinary.dll、php_igbinary.pdb四個文件,移至自己PHP版本對應目錄下的ext文件夾下E:\phpstudy_pro\Extensions\php\php7.3.4nts\ext

      4.修改php.ini

      添加如下代碼:

      extension=php_igbinary.dll
      extension=php_redis.dll

      如果有這兩句可以把前面的分號刪掉,沒有就自己添加上,要注意順序,php_igbinary.dll 要在php_redis.dll 前面

      5.重啟Apache

      重啟后,再運行phpinfo.php,查看是否安裝成功

      二、數據結構

      一共三張表,ab_goods商品表,ab_order訂單表,ab_log日志表

      商品表

      訂單表

      日志表 記錄秒殺信息

      三、代碼

      <?php
      namespace app\index\controller;
      use think\Controller;
      use think\Db;
      use think\cache\driver\Redis;
      
      class Miaosha extends Controller
      {
      
       private $redis = null;
       private $cachekey = null; //緩存變量名
       private $basket = []; //私有數組,存放商品信息
      
       private $store = 50;
      
       /**
       * 購物車初始化,傳入用戶id
       */
       public function __construct()
       {
       parent::__construct();
      
       $this->redis = new \Redis(); // 實例化
       $this->redis->connect('127.0.0.1','6379');
       $this->redis->auth('zxf123456');
      
       }
      
       /**
       * 秒殺初始化
       */
       public function Ms_init()
       {
       // 刪除緩存列表
       $this->redis->del($this->cachekey);
      
       $len = $this->redis->llen($this->cachekey);
       $count = $this->store - $len;
      
       for ($i=0; $i < $count; $i++) { 
      
       // 向庫存列表推進50個,模擬50個商品庫存
       $this->redis->lpush($this->cachekey,1);
       }
      
       echo "庫存初始化完成:".$this->redis->llen($this->cachekey);
       }
       
      
       /**
       * 秒殺入口
       */
       public function index()
       {
       $id = 1; //商品編號
       
       if (empty($id)) {
       // 記錄失敗日志
       return $this->writeLog(0,'商品編號不存在'); 
       }
      
       // 計算庫存列表長度
       $count = $this->redis->llen($this->cachekey);
      
       // 先判斷庫存是否為0,為0秒殺失敗,不為0,則進行先移除一個元素,再進行數據庫操作
       if ($count == 0) { //庫存為0
      
       $this->writeLog(0,'庫存為0');
       echo "庫存為0";
       exit;
      
       }else{
       // 有庫存
       //先移除一個列表元素
       $this->redis->lpop($this->cachekey);
      
       $ordersn = $this->build_order_no(); //生成訂單
       $uid = rand(0,9999); //隨機生成用戶id
       $status = 1;
       // 再進行數據庫操作
       $data = Db::table('ab_goods')->field('count,amount')->where('id',$id)->find(); //查找商品
      
       if (!$data) {
       return $this->writeLog(0,'該商品不存在');
       }
      
       $insert_data = [
       'order_sn' => $ordersn,
       'user_id' => $uid,
       'goods_id' => $id,
       'price' => $data['amount'],
       'status' => $status,
       'addtime' => date('Y-m-d H:i:s')
       ];
      
       // 訂單入庫
       $result = Db::table('ab_order')->insert($insert_data);
       // 自動減少一個庫存
       $res = Db::table('ab_goods')->where('id',$id)->setDec('count');
      
       if ($res) {
       echo "第".$count."件秒殺成功";
       $this->writeLog(1,'秒殺成功');
       }else{
       echo "第".$count."件秒殺失敗";
       $this->writeLog(0,'秒殺失敗');
       }
       }
       }
      
       /**
       * 生成訂單號
       */
       public function build_order_no()
       {
       return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
       }
      
       /**
       * 生成日志 1成功 0失敗
       */
       public function writeLog($status = 1,$msg)
       {
       $data['count'] = 1;
       $data['status'] = $status;
       $data['addtime'] = date('Y-m-d H:i:s');
       $data['msg'] = $msg;
       return Db::table('ab_log')->insertGetId($data);
       }
      
      }

      四、壓力測試

      使用apache壓力測試工具 AB 測試,模擬多用戶秒殺商品,模擬60秒內發起3000個請求,并發600次,秒殺50個庫存商品

      AB測試相關參數說明

      • -r 指定接收到錯誤信息時不退出程序
      • -t 等待響應的最大時間
      • -n 指定壓力測試總共的執行次數
      • -c 用于指定壓力測試的并發數

      1.初始化50個庫存,運行ms_init方法

      2.測試   命令行:

      E:\phpstudy_pro\Extensions\Apache2.4.39\bin>ab -r -t 60 -n 3000 -c 1000 http://gouwuche.zxf/index/miaosha/index  

        3.檢測數據庫數據

      日志表狀態為1(秒殺成功)的數據有50人,訂單表里的訂單數也是50條,商品表里的商品數量變成了0(測試之前是50),商品秒殺成功完成!

      如果不用redis而是直接用mysql的話,商品表訂單的數量count會變成負數,而秒殺成功的人數也多余50人,訂單表里的訂單數量也多余50條(新測),下面是直接用Mysql的例子;

      public function sqlMs()
       {
       $id = 1; //商品編號
      
       $count = 50;
       $ordersn = $this->build_order_no(); //生成訂單
       $uid = rand(0,9999); //隨機生成用戶id
       $status = 1;
       // 再進行數據庫操作
       $data = Db::table('ab_goods')->field('count,amount')->where('id',$id)->find(); //查找商品
      
       // 查詢還剩多少庫存
       $rs = Db::table('ab_goods')->where('id',$id)->value('count');
       if ($rs <= 0) {
       
       $this->writeLog(0,'庫存為0');
       }else{
      
       $insert_data = [
       'order_sn' => $ordersn,
       'user_id' => $uid,
       'goods_id' => $id,
       'price' => $data['amount'],
       'status' => $status,
       'addtime' => date('Y-m-d H:i:s')
       ];
      
       // 訂單入庫
       $result = Db::table('ab_order')->insert($insert_data);
       // 自動減少一個庫存
       $res = Db::table('ab_goods')->where('id',$id)->setDec('count');
      
       if ($res) {
       echo "第".$data['count']."件秒殺成功";
       $this->writeLog(1,'秒殺成功');
       }else{
       echo "第".$data['count']."件秒殺失敗";
       $this->writeLog(0,'秒殺失敗');
       }
       }
       }

      到此這篇關于Thinkphp5+Redis實現商品秒殺的文章就介紹到這了,更多相關Thinkphp5+Redis實現商品秒殺內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

      相關文章

      • ThinkPHP3.1新特性之命名范圍的使用

        ThinkPHP3.1新特性之命名范圍的使用

        ThinkPHP3.1的命名范圍功能,給模型操作提供了一系列的(連貫操作)封裝,讓你更方便的查詢和操作數據。這篇文章主要介紹了ThinkPHP3.1命名范圍的使用,需要的朋友可以參考下
        2014-06-06
      • php redis setnx分布式鎖簡單原理解析

        php redis setnx分布式鎖簡單原理解析

        這篇文章主要介紹了php redis setnx分布式鎖簡單原理解析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
        2020-10-10
      • PHP錯誤處理函數register_shutdown_function使用示例

        PHP錯誤處理函數register_shutdown_function使用示例

        這篇文章主要介紹了PHP錯誤處理函數register_shutdown_function使用示例,需要的朋友可以參考下
        2017-07-07
      • 基于JQuery+PHP編寫砸金蛋中獎程序

        基于JQuery+PHP編寫砸金蛋中獎程序

        砸金蛋被廣泛應用于慶典活動、商家促銷、電視娛樂等場合,它的趣味、懸念能迅速活躍現場氣氛,同樣,我們也可以將砸金蛋應用到WEB網站上,用于開展線上活動,本文將使用jQuery+PHP講解如何實現一個WEB砸金蛋程序,需要的朋友一起來學習吧
        2015-09-09
      • Yii2使用小技巧之通過 Composer 添加 FontAwesome 字體資源

        Yii2使用小技巧之通過 Composer 添加 FontAwesome 字體資源

        前天幫同事改個十年前的網站 bug,頁面上一堆 include require 不禁讓人抱頭痛哭。看到 V2EX 上的討論說,寫 PHP 不用框架等同于耍流氓。Yii Framework 是我使用了 2 年多的 PHP 框架,器大活好,皮實耐操。 Yii2 還在 Beta 中,不過不影響拿來預研。
        2014-06-06
      • 詳解PHP中strlen和mb_strlen函數的區別

        詳解PHP中strlen和mb_strlen函數的區別

        在PHP中,strlen與mb_strlen是求字符串長度的函數,但是對于一些初學者來說,如果不看手冊,也許不太清楚其中的區別
        2014-03-03
      • Thinkphp5框架實現獲取數據庫數據到視圖的方法

        Thinkphp5框架實現獲取數據庫數據到視圖的方法

        這篇文章主要介紹了Thinkphp5框架實現獲取數據庫數據到視圖的方法,涉及thinkPHP5數據庫配置、讀取、模型操作及視圖調用相關操作技巧,需要的朋友可以參考下
        2019-08-08
      • Laravel框架實現model層的增刪改查(CURD)操作示例

        Laravel框架實現model層的增刪改查(CURD)操作示例

        這篇文章主要介紹了Laravel框架實現model層的增刪改查(CURD)操作,結合實例形式分析了Laravel框架模型model層進行數據庫的增刪改查操作具體實現技巧,需要的朋友可以參考下
        2018-05-05
      • 基于PHP實現短信驗證碼接口(容聯運通訊)

        基于PHP實現短信驗證碼接口(容聯運通訊)

        本文分步驟給大家講解了短信驗證碼接口(容聯運通訊)實現代碼,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
        2016-09-09
      • 基于laravel where的高級使用方法

        基于laravel where的高級使用方法

        今天小編就為大家分享一篇基于laravel where的高級使用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
        2019-10-10

      最新評論

      218彩票 www.legallois-ycymro.com:治县。| www.mzlfjsh.com:元江| www.dtyddy.com:宾阳县| www.gzylflzx.com:东乡族自治县| www.fb662.com:获嘉县| www.ahlikartu.com:武义县| www.xfshh.com:彭山县| www.cheap-uggboots4u.com:蒙城县| www.viralcoins.com:沁源县| www.jd2002.net:壤塘县| www.oudianfamen.com:荣成市| www.tlhsny.com:江孜县| www.resortprincipidipiemonte.com:嘉黎县| www.employerlawblog.com:南江县| www.kmm-llc.com:门头沟区| www.silviatenenti.com:遵化市| www.lcompuserve.com:沂水县| www.gayboyfetisch.net:江陵县| www.canchec.com:丰顺县| www.qlookups.com:武山县| www.nba-sports.com:海阳市| www.jordantrainerprime.com:察隅县| www.kneadinbread.com:洮南市| www.wwwe6688.com:昆山市| www.phone-winn4.com:赤壁市| www.ilaoer.com:三门县| www.toystorez.com:四子王旗| www.lplfh.cn:成安县| www.tjjmy.com:安远县| www.chambres-dhotes-le-cigalon.com:云霄县| www.zhongyuanpq.com:宁河县| www.plasticsconsultancy.com:资中县| www.alhondigadigital.com:海城市| www.pj88851.com:荔浦县| www.zxnqw.cn:漳浦县| www.dom19.com:湖州市| www.547291.com:乐昌市| www.fsbaohu.com:视频| www.notarydmv.com:洪泽县| www.busybeesflorist.com:湖南省| www.tiantaojiaosu.com:阿克| www.earncurve.com:霍山县| www.jxyataicy.com:项城市| www.reindeerrowe.com:岑溪市| www.canproimmigration.com:建德市| www.considerthereasons.com:株洲市| www.brandshoesbar.com:长垣县| www.ys2003.com:泌阳县| www.hotmusicpick.com:大同市| www.wwwe6688.com:探索| www.8689msc.com:镇雄县| www.rynhd.com:昭觉县| www.golddragonrecruiter.com:东乡| www.craigsroyal.com:浙江省| www.f5696.com:纳雍县| www.yanhuasoft.com:南昌市| www.mpafoto.com:德钦县| www.cheapcialisnow.net:西充县| www.thedivineasana.com:香格里拉县| www.chord-tutor.com:洛川县| www.apexhealthproducts.com:东乌珠穆沁旗| www.tjjmy.com:霍林郭勒市| www.jnwfm.cn:武安市| www.carbonsilver.com:张家界市| www.rareearthsoil.com:抚松县| www.cleanhouselimpeza.com:黄骅市| www.votextile.com:崇信县| www.kaihongmtc.com:卢龙县| www.f2767.com:宝丰县| www.wordsihate.org:房产| www.mr-impact-windows.com:台东县| www.xqlcw.cn:仁化县| www.fgzcs.com:科技| www.alamtareque.com:桐乡市| www.zheduowang.com:安顺市| www.yzbux.com:日照市| www.wainini.com:乌审旗| www.hdb001.com:台江县| www.conceptmagicevents.com:武清区| www.crecerjuntosmex.com:鲜城| www.cp7576.com:米泉市| www.chryslermodules.com:浙江省| www.jackherbflorist.com:卢龙县| www.davidroemerphotography.com:曲阳县|