用PCNTL扩展,自己模拟多进程实现.
10万条数据 切割成10份.
10个进程 每个进程处理1W条数据.
切割成多少份,随意 20也行.
sql中使用主键id,会使用到覆盖索引,没有SQL性能问题.
请看伪代码
//子进程最大数量
$pMax = 10;
//获取数据最大id 数据可能id不连续,使用max(id) 比使用count(*) 更合理
$sql = "SELECT MAX(id) as count FROM table ";
$count = $db->fetchOne($sql, \Phalcon\Db::FETCH_ASSOC);
$count = $count['count'];
var_dump("数据总数:".$count);
$limit_count = ceil($count / $pMax);
var_dump("每个进程处理数据条数:".$limit_count);
//$sql = " SELECT id FROM `table` WHERE id < {$id} ORDER BY id DESC limit {$limit} ";
//echo "生产者sql:" . PHP_EOL;
//echo $sql . PHP_EOL;
//$data = $db->fetchAll($sql, \Phalcon\Db::FETCH_ASSOC);
// 10个子进程处理任务
$start = self::getMicroTime();
for ($p = 1; $p <= $pMax; $p++) {
sleep(1);
$pid = pcntl_fork();
if ($pid == -1) {
die("could not fork");
} elseif ($pid) {
echo "父进程: $pid\n";
//pcntl_wait($status,WNOHANG);
} else {
// 子进程处理
//$func = $args[0].'Action';
$func = '子进程执行函数名称';
$params = [];
//子进程参数1-当前进程需要处理的数据最大id
$params[1] = $p*$limit_count;
//子进程参数0-进程编号
$params[0] = ($p-1)*$limit_count;
//子进程参数2-进程id
$params[2] = $p;
//子进程参数3-数据内容
$params[3] = $data;
$this->$func($params);
// 一定要注意退出子进程,否则pcntl_fork() 会被子进程再fork,带来处理上的影响。
exit;
}
}
// 等待子进程执行结束
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "子进程 $status 完成\n";
}
看看是否满足你的需求
多进程比较好理解.
如果追求更高性能,可以用Swoole来写,不过还需要额外安装PHP扩展.
有其他疑问,请在评论区交流.