IT技术博客大学习 共学习 共进步

用linux命令提高php的处理能力

PHPec 2009-10-17 14:31:10 浏览 3,301 次

    最近,需要对用户访问日志作一些统计分析处理,该日志每天生成,大小平均是1.5G,经其它程序进行预处理后,去掉一些无关信息,减小为300M左右,格式是userId`url`clicks,1000万行左右.

    要做的工作是按userId,urlId分组保存到数据库,类似这样:

    uid    urlId    clicks

    ------------------------

    12    1    3

    12    2    4

    13    1    3

    13    2    5

    13    11    3

    当然,还有其它关联的表,如url表,需要先通过url在url表查找出urlId,如果没有则插入...满足各种需求后,每条记录操作数据库的平均次数是查询4-6次(包括oracle的获得自增id查询),插入/更新3次

    假设数据库的操作已经完全优化,要完成这项目任务,使用php的常规办法是打开日志文件句柄,然后遍历处理,这样,1000万条记录一下来,不少于6个小时(硬件配置为8G内存+Xeon1.60GHz 4核 x 2 ,下同)

    这样的处理速度明显是不能满足要求的,必须要进行优化,但php本身的优化手段有效,于是,php的好朋友linux上场了:

    1)先对日志文件进行排序处理,排序后,可方便按uid进行合并,大大减少了数据库的操作次数

以下是代码片段:

//对$cTempFile进行排序,生成排序后的$cSwapFile  
$command = "sort {$cTempFile} > {$cSwapFile}";  
system($command,&$returnVar); 

    

    2)对排序后的文件进行切分,启用php模拟进程方式并行处理

以下是代码片段:

$threads = 15; //启动的进程数  
//查询待处理文件的总行数
$command = "cat {$cSwapFile} |wc -l";  
$nums = system($command,&$returnVar);  
$lines = ceil($nums / $threads); //每个文件的行数,用总行数除文件数后取整  
chdir(LOG_PATH);//进入存放切分后文件的路径 

//切分文件,具体参数可查split帮助
$command = "split -d -l {$lines}  {$cSwapFile} temp_custom"; //切成 $lines个文件,文件前缀是tem_custom,以数字后缀结束,如temp_custom00,temp_custom12  
system($command,&$returnVar);  
//切分后,启动进程处理 

$eventLog = LOG_PATH.'eventLog'; //事件日志

for($i = 0;$i< $threads;$i++){  
        $command = sprintf("php %s -f %d >> %s &",__FILE__,$i,$eventLog); //必须将输出重定到日志文件,并加入&在后台执行  
        system($command,&$returnVar);  
}  

    3)进程处理

    主进程通过 php __FILE__ -f id 的方式调用子进程

    因为是同一个文件,需要判断一下$argv参数,并根椐id生成当前进程要处理的日志文件,开始正常处理入库

    经过这样处理后,进程数开到15,同样的日志,全部完成只需1个小时以内,这时cpu的负载还是在极低的水平

    要注意的可能是数据库的处理能力了,如果进程数过大,数据库的吞吐可能会造成瓶颈

    总结:

    1)当需要遍历一个大文件进行时,可以使用切分的方法切成n个较少的文件,再同时并行调用的方式处理,可以有效的减少处理时间.

    2)在遍历入库的操作中,有效的合并可以减少数据库的操作次数

建议继续学习

  1. vim几个小技巧(批量替换,列编辑) (阅读 37,263)
  2. ps - 按进程消耗内存多少排序 (阅读 12,523)
  3. find命令的一点注意事项 (阅读 11,682)
  4. 100个常用的linux命令 (阅读 11,442)
  5. 每个程序员都应该知道的8个Linux命令 (阅读 10,585)
  6. 最受欢迎的10个 Linux 单行命令 (阅读 10,002)
  7. Linux date 命令获取某日期的前一天 (阅读 9,723)
  8. ps 命令常见用法 (阅读 9,322)
  9. Linux常用系统信息查看命令 (阅读 8,501)
  10. Linux 常见高危操作 (阅读 8,262)