亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

PHP讀寫文件高并發處理操作實例詳解

2024-05-05 00:02:57
字體:
來源:轉載
供稿:網友

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

背景:

最近公司游戲開發需要知道游戲加載的流失率。因為,我們做的是網頁游戲。玩過網頁游戲的人都知道,進入游戲前要加載一些資源。最后才能到達創建角色的游戲界面。我們有一個需求就是要統計在加載過程中還未到達角色創建界面而流失的用戶數量。

我們在加載開始就進行統計人數,加載完成之后再記錄人數。這樣,通過用加載前的人數減去成功加載后的人數。就知道了加載的流失率。就可以知道游戲是否還要繼續優化加載過程,降低用戶加載游戲率。

由于,我們的量都是從*主流的合作媒體進行導量過來。所以,并發非常高,據粗略計算應該能達到每秒1000左右的并發數量。

加載前的人數本來想放到游戲內部的緩存平臺。但是,游戲后端的同事擔心并發太高,導致資源無故浪費。因為,內存的釋放并不是實時響應的。所以,將統計的人數放到在另外一臺服務器:統計服務器。

我剛開始采用的方案如下:

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

準確的說,并發的訪問不是順序的。當A玩家加載游戲讀取到文件里面的數字100(假如這時是100),B玩家讀取到的也是100,這時,處理A玩家的線程就是在100的基礎上加1,得到101,就會向文件寫入101。

處理B玩家的線程也得到相同的結果,將101寫入文件。這時,問題就出現了?B玩家是在A玩家之后加載游戲的,理應得到102的計算結果。

這就是并發導致的問題。這個時候,我想到了采用fopen()打開文件,并用flock()加一個寫入鎖。大家一定會認為,這種方式有了鎖定,那么就不會造成問題了。其實,也是錯的。

因為,我們的問題不是出在寫入上面。而是讀取的時候造成數據的不同步。OK。到這里,我實在百度谷歌都搞不定了。

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

但是,用數組的話,也存在一個問題。就是PHP的變量還是常量,在腳本執行完畢之后都會自己清掉。于是,我想到了文件保存的方式。

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

用fopen打開一個文件,以只寫的方式。然后寫鎖定。玩家每加載一次我就向文件里面寫入一個數字1,最后得到的文件內容通過file_get_contents()一次性讀取出來,再用strlen()計算一下長度即知道了有多少玩家加載了游戲。

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

// loadcount.func.php 函數文件。/** * 獲取某來源和某服務器ID的游戲加載次數。 * * @param string $fromid 來源標識。 * @param int $serverid 服務器ID編號。 * * @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);}/** * 獲取某來源所有服務器的游戲加載次數。 * * @param string $fromid 來源標識。 * * @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;}/** * 清空所有的加載數據。 * * @return void */function clearLoadCount(){    foreach (glob("*.txt") as $filename) {      unlink($filename);    }    return true;}/** * 延遲更新游戲加載次數中間件。 * * 使用此函數來延遲更新數據,原理:當不足1000次的時候,不更新數據庫,超過1000就更新到數據庫里面去。 * * @param string $fromid 來源標識。 * @param int $serverid 服務器ID編號。 */function delayAddLoadCount($fromid, $serverid){    // 使用MD5生成文件名記錄緩存次數。    $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;}

以下是我調用以上方法的文件:

< ?php/** * @describe 平臺用戶加載游戲次數統計接口入口。 * @date 2012.12.17 */include_once './loadcount.func.php';// 測試用。// $_GET['fromid']  = '4399';// $_GET['serverid'] = mt_rand(0, 5);// 添加加載次數。if ( $_GET['action'] == 'addcount' ){    $fromid  = $_GET['fromid'];  // 來源標識。    $serverid = $_GET['serverid']; // 服務器ID編號。    $return = delayAddLoadCount($fromid, $serverid);    $return = $return ? 1 : 0;    ob_clean();    echo json_encode($return);    exit;}// 取加載次數。elseif ( $_GET['action'] == 'getcount' ){    $fromid = $_GET['fromid'];  // 來源標識。    if ( !isset( $_GET['serverid'] ) ) // 有服務器編號 ID則取來源對應的服務器加載次數。    {        $count = getAllLoadCount($fromid);    }    else // 加載對應來源的次數。    {        $serverid = $_GET['serverid']; // 服務器ID編號。        $count = getLoadCount($fromid, $serverid);    }    ob_clean();    header('Content-Type:text/html;charset=UTF-8');    $serverid = strlen($serverid) ? $serverid : '無';    echo "來源:{$fromid},服務器ID:{$serverid},游戲加載次數:" . $count;    exit;}// 清除加載次數。elseif ( $_GET['action'] == 'clearcount' ){    header('Content-Type:text/html;charset=UTF-8');    $return = clearLoadCount();    if ($return)    {        echo "清除成功!";    }    else    {        echo "清除失??!";    }}

這是血的教訓,所以,我不得不將它記錄下來。以備以后讓他人借鑒。

本文是作者寒冰一年前在4399游戲工作室負責做數據分析的時候寫的代碼。希望對大家有所幫助。

PHP數據庫操作之高并發實例

高并發下PHP寫文件日志丟失

<?php/** * Created by PhpStorm. * User: andyfeng * Date: 2015/6/24 * Time: 13:31 */class LogFileUtil {  public static $fileHandlerCache;  private static $initFlag = false;  private static $MAX_LOOP_COUNT = 3;  private static function init() {    self::$initFlag = true;    register_shutdown_function(array("LogFileUtil", "shutdown_func"));  }  /**   * 輸出到文件日志   * @param $filePath 文件路徑   * @param $msg 日志信息   * @return int   */  public static function out($filePath, $msg) {    if (!self::$initFlag) {      self::init();    }    return self::internalOut($filePath, $msg);  }  /**   * @param $filePath   * @param $msg   * @param $loop   * @return int   */  private static function internalOut($filePath, $msg, $loop = 0) {    //以防一直添加失敗造成死循環    if ($loop > self::$MAX_LOOP_COUNT) {      $result = 0;    } else {      $loop++;      $fp = self::$fileHandlerCache["$filePath"];      if (empty($fp)) {        $fp = fopen($filePath, "a+");        self::$fileHandlerCache[$filePath] = $fp;      }      if (flock($fp, LOCK_EX)) {        $result = fwrite($fp, $msg);        flock($fp, LOCK_UN);      } else {        $result = self::internalOut($filePath, $msg, $loop);      }    }    return $result;  }  function shutdown_func() {    if (!empty(LogFileUtil::$fileHandlerCache)) {      if (is_array(LogFileUtil::$fileHandlerCache)) {        foreach (LogFileUtil::$fileHandlerCache as $k => $v) {          if (is_resource($v))            //file_put_contents("close.txt",$k);            fclose($v);        }      }    }  }}

希望本文所述對大家PHP程序設計有所幫助。


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲理论在线a中文字幕| 精品伊人久久97| 在线电影av不卡网址| 精品丝袜一区二区三区| 97精品欧美一区二区三区| 欧美午夜激情视频| 日韩欧美成人免费视频| 国模吧一区二区| 亚洲欧美变态国产另类| 成人国产精品日本在线| 久久99热精品这里久久精品| 国内精品久久久久久久| 亚洲黄色在线观看| 久久免费精品视频| 久久久在线免费观看| 久久久久中文字幕2018| 中文字幕9999| 久久免费成人精品视频| 日本久久久久久久久| 最近2019年中文视频免费在线观看| 国产精品精品久久久久久| 亚洲成人激情在线观看| 性色av一区二区三区免费| 久久国产精彩视频| 97视频在线观看播放| 国产精品自产拍在线观看中文| 青青久久av北条麻妃海外网| 国内精品久久久久久中文字幕| 91视频九色网站| 欧美亚洲另类激情另类| 国产成人亚洲综合青青| 成人福利视频在线观看| 国产精品青青在线观看爽香蕉| 亚洲毛片在线免费观看| 2019日本中文字幕| 国产69久久精品成人| 久久国产精品偷| 最近2019年手机中文字幕| 色与欲影视天天看综合网| 精品成人国产在线观看男人呻吟| 国产精品永久免费| 91精品成人久久| 亚洲国产成人爱av在线播放| 中文字幕日韩欧美在线视频| 日韩一区二区av| 国产精品a久久久久久| 91在线观看免费高清| 日韩在线观看免费全集电视剧网站| 色综合久久悠悠| 一区二区三区亚洲| 91精品国产综合久久久久久久久| 久久精品这里热有精品| 国产精品户外野外| 国产精品视频免费观看www| 国产丝袜一区视频在线观看| 亚洲图片欧洲图片av| 久久久久久久国产精品视频| 日本午夜人人精品| 国产精品久久久久影院日本| 日韩美女视频在线观看| 久久福利网址导航| 欧美性猛交99久久久久99按摩| 日韩一区二区三区国产| 亚洲精品乱码久久久久久金桔影视| 日韩欧美黄色动漫| 欧美精品成人在线| 国产福利精品视频| 欧美性猛交99久久久久99按摩| 成人性生交大片免费看小说| 一本色道久久综合亚洲精品小说| 不卡中文字幕av| 日韩国产高清视频在线| 91在线精品视频| 欧美精品www在线观看| 亚洲福利视频网站| 国产日韩在线精品av| 亚洲免费人成在线视频观看| 91高清视频在线免费观看| 国产精品直播网红| 欧美大片免费观看在线观看网站推荐| 粉嫩老牛aⅴ一区二区三区| 久久久91精品| 久久久久久亚洲精品| 亚洲精品中文字幕女同| 国产极品精品在线观看| 日韩动漫免费观看电视剧高清| 久久的精品视频| 岛国精品视频在线播放| 欧美成人免费在线观看| 亚洲福利视频二区| 精品美女久久久久久免费| 中文字幕一区日韩电影| 91成人国产在线观看| 日韩经典中文字幕在线观看| 久久成人免费视频| 久久69精品久久久久久久电影好| 欧美午夜精品久久久久久久| 日韩成人av在线播放| 亚洲理论电影网| 欧美专区在线视频| 国产女人18毛片水18精品| 国产精品国产三级国产aⅴ9色| 国模私拍视频一区| 按摩亚洲人久久| 高清一区二区三区日本久| 欧美日韩人人澡狠狠躁视频| 亚洲黄色av网站| 精品日本美女福利在线观看| 高清欧美性猛交| 亚洲人成网站色ww在线| 神马国产精品影院av| 午夜精品蜜臀一区二区三区免费| 亚洲欧美日韩第一区| 国产91精品视频在线观看| 亚洲国产精品悠悠久久琪琪| 久久91精品国产91久久久| 日韩欧美亚洲范冰冰与中字| 欧美一级大片在线观看| 亚洲精品自拍第一页| 美女性感视频久久久| 国产精品国产福利国产秒拍| 91免费在线视频| 亚洲第一精品夜夜躁人人爽| 97国产成人精品视频| 国产精品三级在线| 亚洲成**性毛茸茸| 成人国产在线视频| 最新中文字幕亚洲| 日韩美女视频在线观看| 欧美一级视频一区二区| 久久深夜福利免费观看| 国产z一区二区三区| 国产玖玖精品视频| 亚洲精品98久久久久久中文字幕| 国产日韩欧美电影在线观看| 国产精品专区一| 亚洲欧美国产精品专区久久| 一区二区中文字幕| 亚洲欧美成人网| 国产日韩欧美视频在线| 欧美精品久久久久| 久久精品国产99国产精品澳门| 亚洲精品av在线| 欧美激情a∨在线视频播放| 欧美黄色片在线观看| 日韩女优人人人人射在线视频| 91精品免费久久久久久久久| 亚洲欧洲国产精品| 美女精品久久久| 中文字幕日本精品| 欧美中文字幕在线播放| 中文字幕亚洲色图| 亚洲国产一区二区三区四区| 国产精品96久久久久久又黄又硬| 亚洲精品免费一区二区三区| 国产网站欧美日韩免费精品在线观看| 中文字幕一区电影| 国产精品777| 亚洲欧美国产视频| 在线看日韩av| 亚洲最大在线视频| 中文字幕精品一区久久久久| 亚洲天堂视频在线观看| 亚洲自拍小视频免费观看|