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表發現商品並沒有超賣現象,日志表成功記錄所以搶購成功或者搶購失敗的日志。
還是有不懂的地方總之能 自己動手寫一遍 收益良多~~
小白一枚 不喜勿噴~~如果我說錯了請指教,如果覺得蠢的話就蠢唄 哈哈哈