高併發關於微博、秒殺搶單等應用場景在PHP環境下結合Redis佇列延遲入庫

OldBoy~發表於2017-05-17

第一步:建立模擬資料表.

CREATE TABLE `test_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL DEFAULT '0' COMMENT '模擬使用者id',
  `username` varchar(200) NOT NULL DEFAULT '' COMMENT '使用者名稱',
  `content` varchar(200) NOT NULL DEFAULT '' COMMENT '內容',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

第二步:來一個隨機生成字串的函式,模擬使用者名稱與內容.

function getStr($length) {
    $chars = array('a','b','c','d','e','f','g','h',
    'i','j','k','l','m','n','o','p','q','r','s',
    't','u','v','w','x','y','z','A','B','C','D',
    'E','F','G','H','I','J','K','L','M','N','O',
    'P','Q','R','S','T','U','V','W','X','Y','Z',
    '0','1','2','3','4','5','6','7','8','9','!',
    '@','#','$','%','^','&','*','(',')','-','_',
    '[',']','{','}','<','>','~','`','+','=',',',
    '.',';',':','/','?','|'); 
    $str = '';
    $count = count($chars);
    for($i=0;$i<$length;$i++){
        $str.= $chars[rand(0,$count-1)];
    }
  return $str;
}

第三步:在配置完成php_redis擴充套件的情況下,寫一個併發指令碼,同時把500條資料放入redis佇列。

$redis = new Redis();  
$redis->connect('127.0.0.1', 6379);  
$info= array(  
    'uid' => rand(1,3000),    //會員uid  
    'username' => getStr(8),    //會員名username 
    'content' => getStr(30),    //內容 
);  
$list = json_encode($info);   //將陣列轉成json來儲存  
$redis->lpush('list',$list);     //lpush向list連結串列對應的頭部新增一個字串元素  
$redis->close();

來用Apache的ab.exe併發測試寫入,不懂得怎麼用ab的看一下這篇文章:簡單模擬一下ab壓力測試

測試寫入佇列500條資料,然後在Redis客戶端用命令:lrange list 0 500 檢視一下

第四步:再來一個實時指令碼把Redis佇列裡的資料延遲寫入資料庫。

set_time_limit(0); // 取消指令碼執行時間的超時上限  
$redis = new Redis();  
$redis->connect('127.0.0.1', 6379);   
while (true) {  
    //返回的列表的大小。如果列表不存在或為空,該命令返回0。如果該鍵不是列表,該命令返回false  
    if($redis -> lsize('list')){  
        //從LIST頭部刪除並返回刪除資料  
        $info = $redis->rpop('list');  
        $info = json_decode($info,true);  
        @$mysql      = mysql_connect('localhost','root','');
mysql_query('SET NAMES utf8');
mysql_select_db('test_db');
$sql = "INSERT INTO test_table(`uid`,`username`,`content`)values ('".$info['uid']."','".$info['username']."',
'".$info['content']."')";
mysql_query($sql);
    }  
    usleep(300);//延時300毫秒  
}  
$redis->close();

第五步:執行入庫檔案,然後檢視資料庫資料。(專案中要把入庫指令碼加入後臺執行)

完畢,大概思路就是這樣的,專案中舉一反三,當然解決的方案有很多。大家盡情思考~

 

相關文章