多线程并发处理大数据量,控制线程数避免内存异常

PHP代码怎么实现多线程并发处理_PHP多进程与pcntl扩展使用

说实话,当我第一次开始使用 PHP 多处理时,我对直接使用 pcntl_fork() 感到非常紧张。
我第一次在 Linux 服务器上运行代码,看到 PID 像雨后蘑菇一样出现。
我当时很兴奋——感觉突然发现PHP也可以灵活。

有趣的是,pcntl很有趣,但是需要类Unix环境。
我在Windows服务器上尝试了这个,结果出现了一个错误,我想用Windows Defender来对抗。
有一次,为了赶一个项目,我半夜在服务器上搭建了Linux环境,编译了PHP,并添加了--enable-pcntl参数。
想想这个过程,我觉得还蛮有耐心的。

使用pcntl_fork()时有一些细节需要特别注意。
比如我之前做过下载,代码写得很简洁。
php $任务 = [ '任务1 :下载文件A'; '任务2 :流程图B'; '任务3 :发送电子邮件C'; '任务4 :备份数据D'; ]; foreach($任务作为$任务){ $pid = pcntl_fork(); 如果($pid==-1 ){ echo "- 无法为 $task\n 创建进程"。
} elseif ($pid == 0) { 回显“[PID”。
getmypid()。
"] 开始:$task\n"; 睡觉(2 ); // 模拟定时操作。
回显“[PID”。
getmypid()。
"] 完成:$task\n"; 退出(0); // 子进程结束。
}
有时父进程先退出,子进程退出还在旋转。
后来我发现我必须手动重用 pcntl_waitpid() 。
如果没有,系统将产生一个僵尸进程 - 我已经多次看到这种情况发生,每次我都必须在系统进程中找到它,就像丢失的 USB 闪存驱动器一样。

说起内存管理,我经历了血泪的教训。
进行视频转换操作时;子进程直接继承父进程的内存。
结果,由于子进程中没有释放临时文件,服务器内存爆炸。
当晚调了半天,终于发现子进程中的大变量是果断撤销。
老实说,这个细节很烦人,但你必须注意它。

但是pcntl说好用但是用起来很累。
后来接触到了消息队列+worker模型,感觉就像坐高铁一样。
记得以前做电商推广系统的时候,直接使用了RabbitMQ+PHP Workers。
运行功率提升数倍,系统稳定性更高。
现在我们团队基本上都是这样使用的;至少运维问题很多舒缓。

谈到线程解决方案,我尝试过pthreads,但说实话,线程之间的同步机制太复杂了。
我在调试线程死锁的时候差点掉头发。
今天,我们通常不会触及这个,除非它是特定于 CPU 的任务。

这需要很长时间,而且我的情况会变得更糟。
总之,pcntl是个好东西;但是,它必须在正确的上下文中使用。
适合灵活的任务;消息队列更可靠;至少我是这么认为的。