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