225153110603554301.jpg
一、多进程主函数ThreadsMain.php 注:计算进程数 = 服务器内核数 * (2~3)倍在多就不太灵了.

   // @Desc   : 查询数据库200个表分多个进程执行
   // @Author : BraveDu
   // @Date   : 2016-01-18

   class ThreadsMain{
    private $dataArr;
    private $excePath; //指定执行PHP的path
    private $phpShell = '/usr/local/bin/php';
    /*
    * @Exp
    * $dataArr = array(
        array => array('./deal.php','param1','param2',...'paramn',
      )
      这里面第一个参数即为$excePath
    */
    function __construct($data,$excePath=''){
        $this->dataArr  = $data;
        $this->excePath = $excePath ? $excePath : '';
    }
    public function runThreads(){
        if(!is_array($this->dataArr)) return false;
        foreach($this->dataArr as $data){
            $pid=pcntl_fork();
            if($pid==-1){ //进程创建失败
                die('fork child process failure!');
            }
            else if($pid){ //父进程处理逻辑
                pcntl_wait($status,WNOHANG);
            }
            else{ //子进程处理逻辑
                $this->excePath ? array_unshift($data,$this->excePath) : $data;
                pcntl_exec($this->phpShell,$data);
            }
        }
    }
}

$array = array(
  array('1'),
  array('a'),
  array('x'),
);
$thread = new ThreadsMain($array,'./test.php');
$result = $thread->runThreads();

二、处理数据库的文件就是普通接收参数查询,这里用test.php 做模拟.

for($i=0;$i<1000;$i++){
    file_put_contents('test_result_'.$argv[1].'.txt',"{$i} \n",FILE_APPEND);
    sleep(1);
}

三、查看后台是子进程的脚本是否运行
ps-ev.jpg

四、确认后即可,杀死进程

ps -ef |grep test.php | awk '{print $2}' | xargs kill -9

五、把4.2G的文件进行分割,然后根据数据id分桶到0~199个文件里面

split -b 30m 文件名. 先把4.2G 打文件分割成小块文件
fileNums=`ls x* | wc -l`
for i in `ls x*`
do
    echo "~~excue~~$i~~~";
    for c in `cat $i`
    do
        if [ $c -eq 0 ]
        then
          continue
        fi
        echo $c >> ../engfile/result_eng_$(( 10#$c%200 ))
    done
    sleep 1
done

到这里文件分桶就完成了.
目前的文件目录为:
engfile/result_eng_0~199
dbfile/result_db_0~199
接下来就相同编号的文件进行对比,输出结果.
输出结果要求:
源文件中是如此格式 :1363655799068800
输出格式要求: <flag:2><md5:f977ecf4297a9d1e83d97093c6edc366><ask_id:1363655799068800>
上代码:

for i in {0..199}
do 
comm <(sort engfile/result_eng_$i|uniq) <(sort dbfile/result_db_$i|uniq) -2 -3 \
| awk '{("echo -n "$0"| md5sum ")|getline a; print $0"\t"a}' \
| awk '{printf "<flag:2><md5:"$2"><ask_id:"$1">""\n"}' >> deleteAllresult.txt
done &

注意了: 在执行这段代码的时候直接在命令窗口执行,不要放入到shell中,要不然总报错command substitution: `comm <(sort

后续:
目的虽然实现了,那这样是否是最好的呢,于是乎我之前把 4.2G的源文件 跟 5.3G的数据库文件直接对比。

comm <(sort engsouce/all.doc.final|uniq) <(sort dbfile/dbfile_all.txt|uniq) -2 -3 \
| awk '{("echo -n "$0"| md5sum ")|getline a; print $0"\t"a}' \
| awk '{printf "<flag:2><md5:"$2"><ask_id:"$1">""\n"}' >> __TestDeal.txt &

来看下CUP和内存使用率
cpu.jpg
发现100% 死个熊的了,具体是谁跑死的CPU呢,再看下面. 有个sort, 单独查下sort是啥东西.
sort.jpg
是对比,发现这种方案不行, kill 掉

总结: 在任何的项目场景中根据手头资源和项目的可应用性而定使用何种解决方案,没有最好的,只有最合适的.