人人人妻人人人妻人人人,99精品国产综合久久久久五月天 ,欧美白人最猛性XXXXX,日韩AV无码免费播放

News新聞

業(yè)界新聞動(dòng)態(tài)、技術(shù)前沿
Who are we?

您的位置:首頁(yè)      樂(lè)道系統(tǒng)FAQ      PHP讀寫文件高并發(fā)處理操作實(shí)例詳解

PHP讀寫文件高并發(fā)處理操作實(shí)例詳解

標(biāo)簽: 發(fā)布日期:2018-04-18 21:57:53 555

本文實(shí)例講述了PHP讀寫文件高并發(fā)處理操作。分享給大家供大家參考,具體如下:

背景:

最近公司游戲開(kāi)發(fā)需要知道游戲加載的流失率。因?yàn)椋覀冏龅氖蔷W(wǎng)頁(yè)游戲。玩過(guò)網(wǎng)頁(yè)游戲的人都知道,進(jìn)入游戲前要加載一些資源。最后才能到達(dá)創(chuàng)建角色的游戲界面。我們有一個(gè)需求就是要統(tǒng)計(jì)在加載過(guò)程中還未到達(dá)角色創(chuàng)建界面而流失的用戶數(shù)量。

我們?cè)诩虞d開(kāi)始就進(jìn)行統(tǒng)計(jì)人數(shù),加載完成之后再記錄人數(shù)。這樣,通過(guò)用加載前的人數(shù)減去成功加載后的人數(shù)。就知道了加載的流失率。就可以知道游戲是否還要繼續(xù)優(yōu)化加載過(guò)程,降低用戶加載游戲率。

由于,我們的量都是從*主流的合作媒體進(jìn)行導(dǎo)量過(guò)來(lái)。所以,并發(fā)非常高,據(jù)粗略計(jì)算應(yīng)該能達(dá)到每秒1000左右的并發(fā)數(shù)量。

加載前的人數(shù)本來(lái)想放到游戲內(nèi)部的緩存平臺(tái)。但是,游戲后端的同事?lián)牟l(fā)太高,導(dǎo)致資源無(wú)故浪費(fèi)。因?yàn)?,?nèi)存的釋放并不是實(shí)時(shí)響應(yīng)的。所以,將統(tǒng)計(jì)的人數(shù)放到在另外一臺(tái)服務(wù)器:統(tǒng)計(jì)服務(wù)器。

我剛開(kāi)始采用的方案如下:

通過(guò)php的file_get_contents()file_put_contents()進(jìn)行讀取與寫入。第一次讀寫就向文件寫入1,第二次加載就在原來(lái)的基礎(chǔ)上加1.以此類推.這種順序的思想完全不存在任何問(wèn)題。問(wèn)題就出在,我們的服務(wù)器不可能是順序形式的。

準(zhǔn)確的說(shuō),并發(fā)的訪問(wèn)不是順序的。當(dāng)A玩家加載游戲讀取到文件里面的數(shù)字100(假如這時(shí)是100),B玩家讀取到的也是100,這時(shí),處理A玩家的線程就是在100的基礎(chǔ)上加1,得到101,就會(huì)向文件寫入101。

處理B玩家的線程也得到相同的結(jié)果,將101寫入文件。這時(shí),問(wèn)題就出現(xiàn)了?B玩家是在A玩家之后加載游戲的,理應(yīng)得到102的計(jì)算結(jié)果。

這就是并發(fā)導(dǎo)致的問(wèn)題。這個(gè)時(shí)候,我想到了采用fopen()打開(kāi)文件,并用flock()加一個(gè)寫入鎖。大家一定會(huì)認(rèn)為,這種方式有了鎖定,那么就不會(huì)造成問(wèn)題了。其實(shí),也是錯(cuò)的。

因?yàn)?,我們的?wèn)題不是出在寫入上面。而是讀取的時(shí)候造成數(shù)據(jù)的不同步。OK。到這里,我實(shí)在百度谷歌都搞不定了。

當(dāng)希望寄托在PHP函數(shù)本身而夢(mèng)碎的時(shí)候,我只能另尋它法。脫離它。于是,我想到了*語(yǔ)言的Map映射的機(jī)制。類似于我們的PHP數(shù)組,每加載一次就我往數(shù)組添加一個(gè)元素。這樣,到最后我只需要count()一下數(shù)組就知道了有多少玩家加載了游戲。

但是,用數(shù)組的話,也存在一個(gè)問(wèn)題。就是PHP的變量還是常量,在腳本執(zhí)行完畢之后都會(huì)自己清掉。于是,我想到了文件保存的方式。

最終的可行方案思路如下:

用fopen打開(kāi)一個(gè)文件,以只寫的方式。然后寫鎖定。玩家每加載一次我就向文件里面寫入一個(gè)數(shù)字1,最后得到的文件內(nèi)容通過(guò)file_get_contents()一次性讀取出來(lái),再用strlen()計(jì)算一下長(zhǎng)度即知道了有多少玩家加載了游戲。

聽(tīng)聞flock()函數(shù)會(huì)鎖定會(huì)造成系統(tǒng)資源在很多時(shí)間升高。所以,我采用大家所使用的方式,用微秒超時(shí)的技術(shù)解決這個(gè)問(wèn)題。如果,走出這個(gè)時(shí)間我就*掉它。具體的代碼如下:

// loadcount.func.php 函數(shù)文件。
/**
 * 獲取某來(lái)源和某服務(wù)器ID的游戲加載次數(shù)。
 *
 * @param string $fromid 來(lái)源標(biāo)識(shí)。
 * @param int $serverid 服務(wù)器ID編號(hào)。
 *
 * @return int
 */
function getLoadCount($fromid, $serverid)
{
    global $g_global;
    $serverid = (int) $serverid;
    $fromid  = md5($fromid);
    $filename = $fromid . $serverid . '.txt';
    $data = file_get_contents($filename);
    return strlen($data);
}
/**
 * 獲取某來(lái)源所有服務(wù)器的游戲加載次數(shù)。
 *
 * @param string $fromid 來(lái)源標(biāo)識(shí)。
 *
 * @return int
 */
function getAllLoadCount($fromid)
{
    global $g_global;
    $fromid  = md5($fromid);
    $count = 0;
    foreach (glob("{$fromid}*.txt") as $filename)
    {
        $file_content = file_get_contents($filename);
        $count += strlen($file_content);
    }
    return $count;
}
/**
 * 清空所有的加載數(shù)據(jù)。
 *
 * @return void
 */
function clearLoadCount()
{
    foreach (glob("*.txt") as $filename) {
      unlink($filename);
    }
    return true;
}
/**
 * 延遲更新游戲加載次數(shù)中間件。
 *
 * 使用此函數(shù)來(lái)延遲更新數(shù)據(jù),原理:當(dāng)不足1000次的時(shí)候,不更新數(shù)據(jù)庫(kù),超過(guò)1000就更新到數(shù)據(jù)庫(kù)里面去。
 *
 * @param string $fromid 來(lái)源標(biāo)識(shí)。
 * @param int $serverid 服務(wù)器ID編號(hào)。
 */
function delayAddLoadCount($fromid, $serverid)
{
    // 使用MD5生成文件名記錄緩存次數(shù)。
    $fromid  = md5($fromid);
    $filename = $fromid . $serverid . '.txt';
    if($fp = fopen($filename, 'a'))
    {
        $startTime = microtime();
        do {
            $canWrite = flock($fp, LOCK_EX);
            if(!$canWrite)
            {
                usleep(round(mt_rand(0, 100)*1000));
            }
        }
        while ( ( !$canWrite ) && ( ( microtime()- $startTime ) < 1000 ) );
        if ($canWrite)
        {
            fwrite($fp, "1");
        }
        fclose($fp);
    }
    return true;
}