php多进程应用场景实例详解(2)
输出结果
c start #1504499765
b start #1504499765
a start #1504499765
b#mailto:444444@163.com
c#mailto:888888@163.com
a#mailto:000000@163.com
b#mailto:555555@163.com
a#mailto:111111@163.com
c#mailto:999999@163.com
c 2 works done # 1504499769
a#mailto:222222@163.com
b#mailto:666666@163.com
b#mailto:777777@163.com
a#mailto:333333@163.com
b 4 works done # 1504499773
a 4 works done # 1504499773
在text_task.php中创建了3个进程(a、b、c),其中a和b处理的文件中有4条记录,c处理的文件中有2条记录。
通过输出结果可以得到:
1. a、b、c 三个进程同时开始执行,开始时间戳1504499765
2. c最先完成,完成时间戳1504499769,耗时4s
3. a和c同时完成,完成时间戳1504499773,耗时8s
处理消息队列
这是另外一种常见的常见,我们将耗时操作放入消息队列,通过脚本从消息队列中取出并执行记录。如果通过单个进程依次读取并处理消息,容易使队列中积累大量数据,导致操作的延迟时间较长,这种场景可以通过多个进程来读取并处理消息。redis中的pop操作具有原子性,不会存在多个读取到相同的队列消息的情况。
多进程调用脚本 redis_task.php
$redis = new Redis();
$redis->connect('192.168.1.10');
$task_key = 'task_list';
$task_list = [
'000000@163.com',
'111111@163.com',
'222222@163.com',
'333333@163.com',
'444444@163.com',
'555555@163.com',
'666666@163.com',
'777777@163.com',
'888888@163.com',
'999999@163.com',
];
foreach ($task_list as $task){
$redis->lPush($task_key,$task);
}
$cmds = [
['/Users/zhezhao/www/work/redis_mail.php','a'],
['/Users/zhezhao/www/work/redis_mail.php','b'],
['/Users/zhezhao/www/work/redis_mail.php','c']
];
foreach ($cmds as $cmd){
$pid = pcntl_fork();
if($pid == -1){
exit('create process failed');
}
if($pid > 0){
pcntl_wait($status,WNOHANG);
}else{
pcntl_exec('/usr/bin/php',$cmd);
}
}
多进程执行脚本 redis_mail.php
require 'MailWork.php';
$name = $argv[1];
echo $name." start #".time().PHP_EOL;
$worker = new MailWork($name);
$redis = new Redis();
$redis->connect('192.168.1.10');
$task_key = 'task_list';
while($redis->lLen($task_key)>0){
$mailto = $redis->rPop($task_key);
$worker->redis_mail($mailto);
}
echo $name." work done # ".time().PHP_EOL;
输出结果
b start #1504499844
c start #1504499844
a start #1504499844
b#mailto:000000@163.com
a#mailto:111111@163.com
c#mailto:222222@163.com
b#mailto:333333@163.com
a#mailto:444444@163.com
c#mailto:555555@163.com
b#mailto:666666@163.com
