大数据量处理实践方案整理

一、数据循环

用 id > $minId limit 1000 这种方式来循环数据。不要用limit 10000,1000这种方式,这种方式在数据量大的时候会非常慢。
用id > $minId limit 1000这种方式来循环时,不要再计算分页,而是要在循环中,或者循环结束后来改变minId的大小,最后将minId做下记录(用文件日志就行),以免程序需要断开或者意外断开时能自动衔接。
示例代码(已做删减,只保留核心代码):

while($minId < $processMaxId){
    $sql = "select id,title from xx where forbid = 1 and id > '{$minId}' and id <= '{$processMaxId}' order by id asc limit {$pageSize}";
    $data = $dbLink->getAll($sql);
    if($data){
        $insertSql = "insert into xx (askid,`type`,url,addtime,`from`,word,lasttime,asktime,replyid,patchNum) values ";
        foreach ($data as $k => $v){
            if($askId > $minId){
                $minId = $askId;
            }
            **UNSET($REPLYLIST,$ASKINFO,$NOW,$ADDTIME,$ASKTIME,$LASTTIME,$FLAG,$ASKID,$TITLE,$CONTENT);**
        }
        $insertSql = rtrim($insertSql,",");
        $dbLink->query($insertSql);
        **UNSET($NOW,$PROCESSSTAGE,$DATA,$LOGSQL,$ASKID);**
    }else{
        $minId += $pageSize;
    }
}
**unset($data,$now,$processStage,$logSql);**

二、每一层循环结束后,清掉所有没用的变量

三、设置更大的内存上限

对于比较消耗内存的,可以在脚本开头设置一个表达的内存上限,避免程序中途因为内存达到上限断掉

ini_set("memory_limit",'3000M');

四、批量插入

insert … values (),()这种

五、多进程

思路,用不同的进程号来区分进程,就像这样:
php a.php 1
php a.php 2
表示进程1和2。根据进程数来计算每个进程所控制的数据段。比如有100万数据,开两个进程,那么进程1负责0-50万,进程2负责50万-100万。
进程中的数据循环和一中将到的循环方式一样,只不过它有个最大id限制。
得到minId和每个进程的最大id:

$minId = file_get_contents($minFile);
$maxId = 1906847;//可以用程序计算max(id)
$processSize = ceil($maxId/5);
$processMaxId = $process * $processSize;
if(!$minId){
    $minId = ($process -1 ) * $processSize;
}

在循环中:

while($minId < $processMaxId){
    $sql = "select id,title from xx_ask where forbid = 1 and id > '{$minId}' and id <= '{$processMaxId}' order by id asc limit {$pageSize}";

##五、进程进度监控
用表来做记录。记录脚本文件、进程号、总进度、批次等信息:

六、守护进程

把需要守护的进程放到自动运行中,每隔一段时间进行监控,如果中断就自动唤起。多进程也适用。

七、多进程管理

进程开关控制。有时候代码写的不完善,需要关掉或者重开,有个脚本比较方便,不用一个个开、关。


$processNum   = $argv[2];   //进程数
$switchButton = $argv[1];   //开关
//自动运行列表
$execLlist = array(
    array(//客户端问答首页列表
        'path' => DIR_PATH.'/Ask/',//文件路径
        'file' => 'xx.php',//执行文件
        'command' => 'mulfil'//口令
    ),
    /*array(//客户端问答首页列表
        'path' => DIR_PATH.'/Ask/',//文件路径
        'file' => 'xx2.php',//执行文件
        'command' => 'mul'//口令
    ),*/
);
foreach ($execLlist as $val) {
    $path    = $val['path'];
    $file    = $val['file'];
    $command = $val['command'];
    if (!$path || !$file) {
        continue;
    }

    for($i = 0; $i < $processNum;$i++) {
        if($i >= 30){
            break;
        }
        $pid = `ps aux|grep "{$file} {$command} {$i} {$processNum}"|grep -v grep|awk '{print $2}'`;
        if ($pid) {
            if($switchButton) {
                echo $path . $file . "此文件已在执行,请耐心等待\n";
                continue;
            }else{
                $cmd = "kill {$pid}";
                exec($cmd);
            }
        }else{
            if($switchButton){
                $cmd = "cd {$path};nohup php {$file} {$command} {$i} {$processNum} > /dev/null &";
                exec($cmd);
            }
        }
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!