處理高併發 IO瓶頸解決紅包程序

解決高併發 io瓶頸解決紅包程序

本程序模擬的紅包抽獎模式。總金額100元,隨機用戶得到1-10元的紅包,直到紅包分發完。
redis中luckMoneyMax須要提早設置php

$r->set('luckMoneyMax' , 100);

正文html

/**
     * 隨機獲取紅包
     * 總金額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 次就抽取完畢redis

毫秒 紅包金額
毫秒時間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元

推薦:
100萬個openid快速存入redissegmentfault

相關文章
相關標籤/搜索