這次給大家帶來php+redis實現商城秒殺功能案例分析(附代碼),php+redis實現商城秒殺功能的注意事項有哪些,下面就是實戰案例,一起來看一下。
1、安裝redis,根據自己的php版本安裝對應的redis擴充(此步驟簡單的描述一下)
1.1.安裝php_igbinary.dll,php_redis.dll擴充此處需要注意你的php版本
1.2.php.ini檔案新增extension=php_igbinary.dll;extension=php_redis.dll兩處擴充
ok此處已經完成第一步redis環境搭建完成看看phpinfo
2、項目中實際使用redis
2.1.第一步配置redis參數如下,redis安裝的預設連接埠為6379:
<?php/* 資料庫配置 */return array( 'DATA_CACHE_PREFIX' => 'Redis_',//緩衝首碼 'DATA_CACHE_TYPE'=>'Redis',//預設動態緩衝為Redis 'DATA_CACHE_TIMEOUT' => false, 'REDIS_RW_SEPARATE' => true, //Redis讀寫分離 true 開啟 'REDIS_HOST'=>'127.0.0.1', //redis伺服器ip,多台用逗號隔開;讀寫分離開啟時,第一台負責寫,其它[隨機]負責讀; 'REDIS_PORT'=>'6379',//連接埠號碼 'REDIS_TIMEOUT'=>'300',//逾時時間 'REDIS_PERSISTENT'=>false,//是否長串連 false=短串連 'REDIS_AUTH'=>'',//AUTH認證密碼 );?>
2.2.實際函數中使用redis:
/** * redis串連 * @access private * @return resource * @author bieanju */ private function connectRedis(){ $redis=new \Redis(); $redis->connect(C("REDIS_HOST"),C("REDIS_PORT")); return $redis; }
2.3. 秒殺的核心問題是在大並發的情況下不會超出庫存的購買,這個就是處理的關鍵所以思路是第一步在秒殺類的先做一些基礎的資料產生:
//現在初始化裡面定義後邊要使用的redis參數public function _initialize(){ parent::_initialize(); $goods_id = I("goods_id",'0','intval'); if($goods_id){ $this->goods_id = $goods_id; $this->user_queue_key = "goods_".$goods_id."_user";//當前商品隊列的使用者情況 $this->goods_number_key = "goods".$goods_id;//當前商品的庫存隊列 } $this->user_id = $this->user_id ? $this->user_id : $_SESSION['uid']; }
2.4. 第二步就是關鍵所在,使用者在進入商品詳情頁前先將當前商品的庫存進行隊列存入redis如下:
/** * 訪問產品前先將當前產品庫存隊列 * @access public * @author bieanju */ public function _before_detail(){ $where['goods_id'] = $this->goods_id; $where['start_time'] = array("lt",time()); $where['end_time'] = array("gt",time()); $goods = M("goods")->where($where)->field('goods_num,start_time,end_time')->find(); !$goods && $this->error("當前秒殺已結束!"); if($goods['goods_num'] > $goods['order_num']){ $redis = $this->connectRedis(); $getUserRedis = $redis->hGetAll("{$this->user_queue_key}"); $gnRedis = $redis->llen("{$this->goods_number_key}"); /* 如果沒有會員進來隊列庫存 */ if(!count($getUserRedis) && !$gnRedis){ for ($i = 0; $i < $goods['goods_num']; $i ++) { $redis->lpush("{$this->goods_number_key}", 1); } } $resetRedis = $redis->llen("{$this->goods_number_key}"); if(!$resetRedis){ $this->error("系統繁忙,請稍後搶購!"); } }else{ $this->error("當前產品已經秒殺完!"); } }
接下來要做的就是用ajax來非同步處理使用者點擊購買按鈕進行合格資料進入購買的排隊隊列(如果目前使用者沒在當前產品使用者的隊列就進入排隊並且pop一個庫存隊列,如果在就拋出,):
/** * 搶購商品前處理當前會員是否進入隊列 * @access public * @author bieanju */ public function goods_number_queue(){ !$this->user_id && $this->ajaxReturn(array("status" => "-1","msg" => "請先登入")); $model = M("flash_sale"); $where['goods_id'] = $this->goods_id; $goods_info = $model->where($where)->find(); !$goods_info && $this->error("對不起當前商品不存在或已下架!"); /* redis 隊列 */ $redis = $this->connectRedis(); /* 進入隊列 */ $goods_number_key = $redis->llen("{$this->goods_number_key}"); if (!$redis->hGet("{$this->user_queue_key}", $this->user_id)) { $goods_number_key = $redis->lpop("{$this->goods_number_key}"); } if($goods_number_key){ // 判斷使用者是否已在隊列 if (!$redis->hGet("{$this->user_queue_key}", $this->user_id)) { // 插入搶購使用者資訊 $userinfo = array( "user_id" => $this->user_id, "create_time" => time() ); $redis->hSet("{$this->user_queue_key}", $this->user_id, serialize($userinfo)); $this->ajaxReturn(array("status" => "1")); }else{ $modelCart = M("cart"); $condition['user_id'] = $this->user_id; $condition['goods_id'] = $this->goods_id; $condition['prom_type'] = 1; $cartlist = $modelCart->where($condition)->count(); if($cartlist > 0){ $this->ajaxReturn(array("status" => "2")); }else{ $this->ajaxReturn(array("status" => "1")); } } }else{ $this->ajaxReturn(array("status" => "-1","msg" => "系統繁忙,請重試!")); } }
附加一個調試的函數,刪除指定隊列值:
public function clearRedis(){ set_time_limit(0); $redis = $this->connectRedis(); //$Rd = $redis->del("{$this->user_queue_key}"); $Rd = $redis->hDel("goods49",'使用者id''); $a = $redis->hGet("goods_49_user", '使用者id'); if(!$a){ dump($a); } if($Rd == 0){ exit("Redis隊列已釋放!"); } }
走到此處的時候秒殺的核心基本就完了,細節還需要自己在去完善,像購物車這邊的處理還有訂單的處理,好吧開始跑程式利用apache自身的ab可以進行簡單的類比並發測試如下:
跑起來,我擦跑步起來redis沒有任何反應,此時還少一步重要的步驟就是開啟redis服務,請根據自己的系統下一個redisbin_x32或者redisbin_x64的redis服務管理工具,點擊redis-server.exe,ok至此全部完成如:
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
推薦閱讀:
PHP的RSA加密解密與開發介面案例流量分析
PHP長串連使用案例分析