PHP之多进程
來源:http://blog.sina.com.cn/s/blog_65e2f28901016q9z.html
 
本來沒想過對進程之類的東西進行研究,但是最近遇到了一個問題,就是在公司的網站中,有時候會需要進行大數據量的運算,例如進行10萬以上的用戶批量關注。或者對一個不斷增長的數據表數據,進行大批量的處理。
???按照以前的想法,那就是一條一條的進行處理唄,反正計算機運算的速度,應該是比較快的吧。實際的運算速度確不那么理想。尤其是針對數據庫或者平臺接口的讀寫操作時,大數據量的讀寫都還是比較慢的。就找了找一些多線程或者多進程處理的資料。一個程序處理是挺慢的,但是數據庫和平臺接口一般來說都是支持多線程并發操作的。那就Google吧。
???PHP本身是沒有多線程的概念。但是PHP自身帶有pcntl_fork函數,PHP手冊是這樣來說明此函數的:Thepcntl_fork()?functioncreates a child process that differs from the parent process onlyin its PID and PPID. Please see your system's fork(2) man page forspecific details as to how fork works on your system.當成功時,返回子進程的pid,失敗返回-1,但前進程為子進程時,返回0。由于函數本身依賴于操作系統的fork來實現,所以此函數只能在linux或者Unix操作系統下使用,windows操作系統下的服務器是不成功的。
???一般的起子進程的寫法是:
 <?php
 $pid = pcntl_fork();
 if($pid == -1){
 ????????//創建失敗
 ????????die('could not fork');
 }
 else{
 ????????if($pid){
 ????????????????//從這里開始寫的代碼是父進程的
 ?? ?? ? ?? ? exit("parent!");
 ????????}
 ????????else{
 ????????????????//子進程代碼,為防止不停的啟用子進程造成系統資源被耗盡的情況,一般子進程代碼運行完成后,加入exit來確保子進程正常退出。
 ????????????????exit("child");
 ????????}
 }
 ?>
???上邊的代碼如果創建子進程成功的話,系統就有了2個進程,一個為父進程,一個為子進程,子進程的id號為$pid。在系統運行到$pid =pcntl_fork();時,在這個地方進行分支,父子進程各自開始運行各自的程序代碼。代碼的運行結果是parent和child,很奇怪吧,為什么一個if和else互斥的代碼中,都輸出了結果?其實是像上邊所說的,代碼在pcntl_fork時,一個父進程運行parent,一個子進程運行了child。在代碼結果上就顯示了parent和child。至于誰先誰后的問題,這得要看系統資源的分配了。
???如果需要起多個進程來處理數據,可以根據數據的數量,按照約定好的數量比如說1000條一個進程來起子進程。使用for循環就可以了。
 
 ???#如果獲得的總數小于或等于0,等待60秒,并退出
 ??? if ($count<= 0)?
 ??? {
 ???????sleep(60);
 ???????exit;
 ??? }
 ???#如果大于1000,計算需要起的進程數
 ??? if ($count> 1000)
 ??? {
 ???????$cycleSize = ceil($count/1000);
 ??? }
 ??? else
 ??? {
 ???????$cycleSize = 1;
 ??? }
 ????
 ??? for ($i=0;$i<$cycleSize; $i++)
 ??? {
 ???????$pid??? =pcntl_fork();
 ???????if($pid == -1)
 ???????{
 ???????????break;
 ???????}
 ???????else
 ???????{
 ???????????if($pid)
 ???????????{
 ???????????????#父進程獲得子進程的pid,存入數組
 ???????????????$pidArr[] = $pid;
 ???????????}
 ???????????else
 ???????????{
 ???????????????//開始發送,子進程執行完自己的任務后,退出。
 ???????????????????exit;
 ???????????}
 ???????}
 ??? }
 ????
 ???while(count($pidArr) > 0)
 ??? {
 ???????$myId?? = pcntl_waitpid(-1,$status, WNOHANG);
 ???????foreach($pidArr as $key => $pid)
 ???????{
 ???????????if($myId == $pid) unset($pidArr[$key]);
 ???????}
 ??? }
???然后使用crontab,來使此PHP程序每隔一段時間自動執行。
???當然,示例代碼比較簡單,具體還需要考慮怎么防止多個子進程執行到同一條數據或者當前進程處理數據未完成時,crontab又開始執行PHP文件啟用新的進程等等。
與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
                            
                        - 上一篇: 无水硫酸铜(说一说无水硫酸铜的简介)
 - 下一篇: 吃馒头时为什么会变甜?