程序、執行緒、協程
- 程序:應用程式的啟動例項,執行起的程式碼叫程序,有獨立的記憶體空間,類比工廠的P個(P=1單程序,P>1多程序)車間。
- 執行緒:執行緒是CPU排程的最小單位,是程序內的執行單元,多個執行緒共享所屬程序的資源。類比車間內的T個員工(T=1單執行緒,T>1多執行緒)車間。
- 協程:類似執行緒,協程是使用者態(CPU受限執行使用者程式指令),執行緒是核心態(CPU任意可在作業系統中任意執行任何指令)。通常在函式內部執行,並且可以在函式的不同部分之間暫停和恢復執行(最明顯的特點就是協程不一定會跟著函式的return而結束,下次呼叫時能保留上呼叫時的狀態)。
多程序、多執行緒怎麼選?
做PHP的是幾乎不用考慮的,畢竟不是C/C++這種偏底層適合做C/S或單Client的應用,PHP大多都是LAMP或LNMP的架構,結合Windows Server用IIS多執行緒的從來還沒有遇見過。
- 多程序適用場景:
- CPU密集型任務:對於需要大量計算的任務,多程序可以充分利用多核處理器的優勢,提高整體處理速度。
- 獨立性要求高:如果任務之間需要完全獨立的記憶體空間和資源,避免相互影響,多程序是更好的選擇。
- 故障隔離:多程序能夠提供更好的故障隔離性,一個程序崩潰不會影響其他程序,提高了系統的可靠性。
- 跨平臺相容性:多程序在跨平臺相容性方面表現更好,因為不同作業系統有不同的執行緒實現,而程序模型更為統一。
- 多執行緒適用場景:
- I/O密集型任務:對於需要頻繁進行I/O操作的任務,多執行緒能夠更好地利用等待時間,提高系統的響應速度。
- 資源共享:多執行緒適用於需要共享資料或資源的場景,能夠更輕鬆地實現資料共享和通訊。
- 實時性要求高:多執行緒能夠更快速地響應事件和處理任務,適合需要實時性的應用場景。
- 記憶體消耗較低:執行緒間共享同一程序的記憶體空間,相比多程序消耗的記憶體較少。
- GUI程式設計:圖形介面程式通常需要不同的執行緒處理使用者互動和介面更新,多執行緒能夠提高介面的響應性和流暢性。
多執行緒實現
- parallel:是適用於 PHP ≥ 7.2.0 的並行併發擴充套件。
- 要求:自 parallel 1.2.0 起,要求 PHP ≥ 8.0.0,必須用ZTS版本(./configure時PHP7需要加--enable-maintainer-zts,PHP>=8需要加--enable-zts)。
- Github地址:https://github.com/krakjoe/parallel
- 使用說明:https://www.php.net/manual/zh/intro.parallel.php
- 下載地址:https://pecl.php.net/package/parallel
- 應用場景:
- 並行資料處理:對大量資料進行並行處理,如影像處理、影片處理、大規模資料分析等。
- 網路請求並行處理:同時傳送多個網路請求,例如同時請求多個API或網頁資料,以提高資料獲取速度。
- 平行計算:執行需要大量計算的任務,如數值計算、科學計算等。
- 並行爬蟲:爬取網頁資料時,可以利用並行處理提高爬取效率,加快資料採集速度。
- 多工排程:在需要同時執行多個任務的場景,可利用此擴充套件進行任務排程和執行,提高系統的併發處理能力。
- 實操
cd /test
wget https://pecl.php.net/get/parallel-1.2.1.tgz
tar zxf parallel-1.2.1.tgz
cd parallel-1.2.1/
/usr/local/php/bin/phpize
./configure
make
make install
vim /usr/local/php/etc/php.ini
extension=parallel
常規測試,輸出@@@%%%,說明程式是從上到下依次執行的。
vim /test/a.php
<?php
for($i = 0; $i < 3; $i ++) {
echo '@';
}
for($j = 6; $j < 9; $j ++) {
echo '%';
}
使用擴充套件執行
<?php
$runtime = new \parallel\Runtime();
$future = $runtime->run(function(){
for ($i = 0; $i < 25; $i ++)
echo "@";
return "result";
});
for ($j = 0; $j < 25; $j ++) {
echo "%";
}
print_r($future->value());
多次執行,效果是這樣的,可見是多個執行緒交替執行。
%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
@%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
%%%%%%%%%%%%%%%%%%%%@%@@@@@@@@@@@@@@@%%@@@@@@@@@%%result[root@localhost test]# php a.php
%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
%%%%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
%%%%%%%%%%%%%%%%%%%%%%%%@%@@@@@@@@@@@@@@@@@@@@@@@@result[root@localhost test]# php a.php
原生協程實現
- 說明:之前的文章就有用到,把9.7GB的文字資料,按照一行一條資料的方式匯入資料庫,如果一次性載入,記憶體過載會報錯。
所以就需要協程來幫忙,PHP的協程使用yield關鍵字來實現
,在匯入過程中,就用到了,協程不一定會跟著函式的return而結束,下次呼叫時能保留上呼叫時的狀態的特點 - 協程適用場景之一:萬字詳解PHP+Sphinx中文億級資料全文檢索實戰(實測億級資料0.1秒搜尋耗時)
- 示例:
- 程式碼不多,就可以實現,就例如大名鼎鼎的單例模式,也沒幾行就能實現,概念指定的程式碼不在多少,在於解決的問題。
- 如下:yield相當於return的返回之意,且不會中斷,還能記住上次迭代的位置,所以輸出的結果是0123456789。
<?php
function func() {
$i = 0;
while ($i < 10) {
yield $i;
$i ++;
}
}
$func = func();
foreach($func as $v) {
echo $v;
}
多程序方式
- 說明:最常見的執行方式,大部分企業都這種架構,不必過多演示。configure時需要新增--enable-fpm --with-fpm-user=www --with-fpm-group=www。與Nginx通訊,通常使用php-fpm(php程序管理器)去實現多個程序。
- 解決問題:
- 提高併發量:請求量一上來,一個程序扛不住,就多個程序一起抗。
- 程序隔離:PHP-FPM 可以實現程序隔離,一個程序的崩潰不會影響到其他程序,提高了系統的穩定性和可靠性。
- 提高資源利用率:PHP-FPM 可以根據實際情況調整程序池的大小,以適應伺服器負載的變化,從而更好地利用伺服器資源,避免資源浪費。
ps aux | grep php
root 3511 0.0 0.3 172232 5936 ? Ss Mar17 1:20 php-fpm: master process (/usr/local/php/etc/php-fpm.conf)
www 4554 0.0 0.7 178812 14516 ? S 15:13 0:01 php-fpm: pool www
www 4555 0.0 0.7 178812 14444 ? S 15:13 0:01 php-fpm: pool www
www 4556 0.0 0.7 178812 14500 ? S 15:13 0:01 php-fpm: pool www
www 4596 0.0 0.7 178812 14496 ? S 15:14 0:01 php-fpm: pool www
www 4597 0.0 0.7 178812 14556 ? S 15:14 0:01 php-fpm: pool www
ZTS、NTS、TS版本的區別
-
ZTS:指的是 PHP 的執行緒安全版本。PHP ZTS 版本中的核心功能被修改和重新編寫,以確保在多執行緒環境下能夠安全地執行。這樣,開發人員就可以在需要在多執行緒環境中執行 PHP 指令碼時,選擇使用 PHP ZTS 版本來提高執行緒安全性和穩定性。
總的來說,PHP ZTS(Zend Thread Safety)是 PHP 的執行緒安全版本,專門設計用於在多執行緒環境下提供更好的執行緒安全性和穩定性。 -
TS:多執行緒訪問時,採用了加鎖機制,當一個執行緒訪問某些資料時進行保護,其它執行緒不能進行訪問,直到該執行緒讀取完,其它執行緒才可使用。主要是針對windows系統iis執行的情況,如果是使用ISAPI的方式來執行PHP就必須用Thread Safe(執行緒安全)的版本。因為windows申請程序開銷較大,所以windows主要以多執行緒方式執行PHP,這時候需要執行緒安全的版本。
-
NTS:linux下,PHP使用多程序方式執行,所以可以選擇nts版本。
ISAPI全稱Internet Server Application Programming Interface,是一種微軟Windows平臺下的Web伺服器擴充套件技術。它允許開發者編寫動態網頁應用程式並直接執行在Web伺服器上,可以與Web伺服器(如IIS)直接互動,提供更高效的效能和更靈活的功能擴充套件。透過ISAPI,開發者可以使用C++、Delphi等語言編寫高效能的Web應用程式。 -
如果要開多執行緒:ZTS優於TS優於NTS。