解決高併發 io瓶頸解決紅包程式
本程式模擬的紅包抽獎模式。總金額100元,隨機使用者獲得1-10元的紅包,直到紅包分發完。
redis中luckMoneyMax需要提前設定
$r->set(`luckMoneyMax` , 100);
正文
/**
* 隨機獲取紅包
* 總金額100元
* 每次紅包大小[1,10]
*/
public function luckMoney()
{
$r = new Redis();
$r->pconnect(`127.0.0.1`,`6379`);
$r->select(1);
$lock_key = `lockkey`;
while(true){
$lock_timout = time()+3+1;
//4秒超時 一個鎖超過4s還沒釋放 說明得到鎖的執行緒掛了 其他執行緒需要競爭釋放鎖 再得到鎖
$get_lock = $r->setnx($lock_key,$lock_timout);
//得到鎖的條件 setnx返回值為真 超時並且getSet保證了不會多個程式去釋放鎖
$now = time();
if($get_lock || ( ($now > $r->get($lock_key)) && ($now > $r->getSet($lock_key , $lock_timout)) ) ){
echo `去抽獎!<br>`;
break;//去抽獎
}
}
$luckMoneyMax = $r->get(`luckMoneyMax`);
if($luckMoneyMax <= 0){
echo `獎金池空了!`;
if((time() < $lock_timout) && $r->del($lock_key)){
echo `<br>毫秒時間:`.$this->msectime().`釋放鎖成功`;
}
return;
}elseif($luckMoneyMax <= 1){
$redBag = $luckMoneyMax;
$r->set(`luckMoneyMax` , 0);
$data_arr = [
`redBag`=>$redBag,
`mstime`=>$this->msectime()
];
$r->lpush("redBag-list", serialize($data_arr));
echo `恭喜中獎`.$redBag;
if((time() < $lock_timout) && $r->del($lock_key)){
echo `<br>毫秒時間:`.$this->msectime().`釋放鎖成功`;
}
return;
}
//1-10 十元整數
$redBag = rand(1,10);
$tmp_money = $luckMoneyMax-$redBag;
if($tmp_money < 0){
$redBag = $luckMoneyMax;
$tmp_money=0;
}
$r->set(`luckMoneyMax` , $tmp_money);
$data_arr = [
`redBag`=>$redBag,
`mstime`=>$this->msectime()
];
$r->lpush("redBag-list", serialize($data_arr));
echo `恭喜中獎`.$redBag.`元`;
if((time() < $lock_timout) && $r->del($lock_key)){
echo `<br>毫秒時間:`.$this->msectime().`釋放鎖成功`;
}
}
/**
* 毫秒級
* @return float
*/
public function msectime() {
list($msec, $sec) = explode(` `, microtime());
$msectime = (float)sprintf(`%.0f`, (floatval($msec) + floatval($sec)) * 1000);
return $msectime;
}
swoole多執行緒測試
<?php
echo "start:".date("Y-m-d H:i:s").PHP_EOL;
for ($i=0 ; $i<100 ;$i++){
$red_process = new swoole_process(`getMoney`,true);
$red_process->start();
echo PHP_EOL;//PHP_EOL換行的意思
echo $red_process->read();
echo PHP_EOL;
}
echo "end:".date("Y-m-d H:i:s").PHP_EOL;
function getMoney(swoole_process $worker)
{
$content = getHTTPS(`http://example.com/index/index/luckMoney.html`);
$worker->write($content);
}
function getHTTPS($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
日誌記錄結果
2s 100 次就抽取完畢
毫秒 | 紅包金額 |
---|---|
毫秒時間1514386342125 | 紅包10元 |
毫秒時間1514386342106 | 紅包10元 |
毫秒時間1514386342086 | 紅包10元 |
毫秒時間1514386342066 | 紅包7元 |
毫秒時間1514386342046 | 紅包6元 |
毫秒時間1514386342026 | 紅包5元 |
毫秒時間1514386342007 | 紅包3元 |
毫秒時間1514386341988 | 紅包1元 |
毫秒時間1514386341968 | 紅包7元 |
毫秒時間1514386341950 | 紅包5元 |
毫秒時間1514386341931 | 紅包8元 |
毫秒時間1514386341913 | 紅包7元 |
毫秒時間1514386341894 | 紅包1元 |
毫秒時間1514386341875 | 紅包1元 |
毫秒時間1514386341856 | 紅包9元 |
毫秒時間1514386341836 | 紅包10元 |
合計 | 100元 |