詳解thinkphp+redis+隊列的實現(xiàn)代碼
1,安裝Redis,根據(jù)自己的PHP版本安裝對應(yīng)的redis擴展(此步驟簡單的描述一下)
1.1,安裝 php_igbinary.dll,php_redis.dll擴展此處需要注意你的php版本如圖:
1.2,php.ini文件新增 extension=php_igbinary.dll;extension=php_redis.dll兩處擴展
ok此處已經(jīng)完成第一步redis環(huán)境搭建完成看看phpinfo

項目中實際使用redis
2.1,第一步配置redis參數(shù)如下,redis安裝的默認端口為6379:
<?php /* 數(shù)據(jù)庫配置 */ return array( 'DATA_CACHE_PREFIX' => 'Redis_',//緩存前綴 'DATA_CACHE_TYPE'=>'Redis',//默認動態(tài)緩存為Redis 'DATA_CACHE_TIMEOUT' => false, 'REDIS_RW_SEPARATE' => true, //Redis讀寫分離 true 開啟 'REDIS_HOST'=>'127.0.0.1', //redis服務(wù)器ip,多臺用逗號隔開;讀寫分離開啟時,第一臺負責(zé)寫,其它[隨機]負責(zé)讀; 'REDIS_PORT'=>'6379',//端口號 'REDIS_TIMEOUT'=>'300',//超時時間 'REDIS_PERSISTENT'=>false,//是否長連接 false=短連接 'REDIS_AUTH'=>'',//AUTH認證密碼 ); ?>
2.2,實際函數(shù)中使用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,秒殺的核心問題是在大并發(fā)的情況下不會超出庫存的購買,這個就是處理的關(guān)鍵所以思路是第一步在秒殺類的先做一些基礎(chǔ)的數(shù)據(jù)生成:
//現(xiàn)在初始化里面定義后邊要使用的redis參數(shù)
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";//當(dāng)前商品隊列的用戶情況
$this->goods_number_key = "goods".$goods_id;//當(dāng)前商品的庫存隊列
}
$this->user_id = $this->user_id ? $this->user_id : $_SESSION['uid'];
}
2.4,第二步就是關(guān)鍵所在,用戶在進入商品詳情頁前先將當(dāng)前商品的庫存進行隊列存入redis如下:
/**
* 訪問產(chǎn)品前先將當(dāng)前產(chǎn)品庫存隊列
* @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("當(dāng)前秒殺已結(jié)束!");
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("系統(tǒng)繁忙,請稍后搶購!");
}
}else{
$this->error("當(dāng)前產(chǎn)品已經(jīng)秒殺完!");
}
}
接下來要做的就是用ajax來異步的處理用戶點擊購買按鈕進行符合條件的數(shù)據(jù)進入購買的排隊隊列(如果當(dāng)前用戶沒在當(dāng)前產(chǎn)品用戶的隊列就進入排隊并且pop一個庫存隊列,如果在就拋出,):
/**
* 搶購商品前處理當(dāng)前會員是否進入隊列
* @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("對不起當(dāng)前商品不存在或已下架!");
/* 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" => "系統(tǒng)繁忙,請重試!"));
}
}
附加一個調(diào)試的函數(shù),刪除指定隊列值:
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隊列已釋放!");
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
yii框架結(jié)合charjs統(tǒng)計上一年與當(dāng)前年數(shù)據(jù)的方法示例
這篇文章主要介紹了yii框架結(jié)合charjs統(tǒng)計上一年與當(dāng)前年數(shù)據(jù)的方法,涉及Yii框架后臺數(shù)據(jù)查詢、前臺交互、日期操作等相關(guān)使用技巧,需要的朋友可以參考下2020-04-04
PHP設(shè)計模式之觀察者模式入門與應(yīng)用案例詳解
這篇文章主要介紹了PHP設(shè)計模式之觀察者模式入門與應(yīng)用,結(jié)合具體案例形式詳細分析了PHP觀察者模式的相關(guān)概念、原理、使用方法及操作注意事項,需要的朋友可以參考下2019-12-12
phpQuery讓php處理html代碼像jQuery一樣方便
這篇文章主要介紹了phpQuery讓php處理html代碼像jQuery一樣方便,需要的朋友可以參考下2015-01-01
Laravel中validation驗證 返回中文提示 全局設(shè)置的方法
今天小編就為大家分享一篇Laravel中validation驗證 返回中文提示 全局設(shè)置的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
laravel 解決多庫下的DB::transaction()事務(wù)失效問題
今天小編就為大家分享一篇laravel 解決多庫下的DB::transaction()事務(wù)失效問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
PHP輸出當(dāng)前進程所有變量/常量/模塊/函數(shù)/類的示例
PHP輸出當(dāng)前進程所有變量、常量、模塊、函數(shù)、類的示例2013-11-11

