溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

為什么PHP Opcache 緩存刷新不了、代碼重載而且無法更新代碼

發(fā)布時(shí)間:2021-03-04 17:19:46 來源:億速云 閱讀:420 作者:TREX 欄目:開發(fā)技術(shù)

這篇文章主要介紹“為什么PHP Opcache 緩存刷新不了、代碼重載而且無法更新代碼”,在日常操作中,相信很多人在為什么PHP Opcache 緩存刷新不了、代碼重載而且無法更新代碼問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”為什么PHP Opcache 緩存刷新不了、代碼重載而且無法更新代碼”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

問題背景

通過啟用Opcache的緩存優(yōu)化,將PHP代碼預(yù)編譯為Opcode緩存到共享內(nèi)存中供進(jìn)程反復(fù)調(diào)用,從而減少了重復(fù)從磁盤解析PHP代碼的時(shí)間消耗,顯著的提高了PHP性能,提升了業(yè)務(wù)性能的調(diào)用,但是也引發(fā)了一些問題,就是我們每次更新了相應(yīng)的PHP代碼后,web server 無法即時(shí)加載到更新后的代碼。

解決方案

(一)、設(shè)置Opcache腳本驗(yàn)證時(shí)間

可以通過更改 Opcache 以下兩個(gè)配置選項(xiàng)來調(diào)整代碼重載時(shí)間

opcache.revalidate_freq=0 檢查腳本時(shí)間戳是否有更新的周期,以秒為單位。(如果設(shè)置為 0 會(huì)導(dǎo)致針對(duì)每個(gè)請(qǐng)求, OPcache 都會(huì)檢查腳本更新)

opcache.validate_timestamps=0 如果啟用,那么 OPcache 會(huì)每隔 opcache.revalidate_freq 設(shè)定的秒數(shù) 檢查腳本是否更新。

PS:在實(shí)際生產(chǎn)環(huán)境中,為了盡可能達(dá)到最優(yōu)性能,盡量不開啟文件更新驗(yàn)證,因?yàn)槊看悟?yàn)證都會(huì)重新預(yù)編譯PHP代碼到共享內(nèi)存中。

(二)、重啟 | 重載 php-fpm 進(jìn)程

每次重啟或重啟 php-fpm 進(jìn)程便會(huì)重新解析PHP腳本文件,但是重啟 fpm 進(jìn)程可能會(huì)導(dǎo)致請(qǐng)求中斷,從而導(dǎo)致寫入臟數(shù)據(jù) 或者 造成事務(wù)回滾等一系列異常。

重載相對(duì)于重啟則平順很多,不會(huì)導(dǎo)致用戶請(qǐng)求直接中斷,相對(duì)來說風(fēng)險(xiǎn)低很多,但是php-fpm 收到reload信號(hào),便會(huì)向所有子進(jìn)程發(fā)送SIGGUIT信號(hào),同時(shí)注冊(cè)一個(gè)定時(shí)器,在規(guī)定的時(shí)間之內(nèi)子進(jìn)程沒有退出,接著在發(fā)送SIGTERM信號(hào),結(jié)束子進(jìn)程。如果在一秒之內(nèi)子進(jìn)程還是沒結(jié)束 直接發(fā)送SIGKILL 強(qiáng)制殺死。

重啟php-fpm

service php-fpm restart

重載php-fpm

services php-fpm reload

或 kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

(三)、手動(dòng)清理緩存

除了上面的兩種方式,還有更為穩(wěn)妥一點(diǎn)的緩存清理,我們可以通過opcache_reset()和opcache_invalidate() 函數(shù)來刷新Opcache緩存。

opcache_reset() - 重置整個(gè)Opcode緩存,所有的PHP腳本將會(huì)被重新解析再預(yù)編譯為Opcode。

opcache_invalidate() - 清除指定腳本緩存,可以傳遞兩個(gè)參數(shù),一個(gè)是刷新文件路徑,一個(gè)是force字段, 如果 force 沒有設(shè)置或者傳入的是 FALSE,那么只有當(dāng)腳本的修改時(shí)間 比對(duì)應(yīng)Opcode的時(shí)間更新時(shí),腳本的緩存才會(huì)失效。

需要注意的是,當(dāng)PHP以PHP-FPM的方式運(yùn)行的時(shí)候,opcache的緩存是無法通過php命令進(jìn)行清除的,只能通過http或cgi到php-fpm進(jìn)程的方式來清除緩存,我們可以編寫一個(gè)對(duì)外接口,來達(dá)到清理緩存的目的。

相關(guān)實(shí)現(xiàn)如下(框架:laravel):

Route::any('cache-reset', function () {
  //重置整個(gè)Opcode緩存
  dd(opcache_reset());
});

Route::any('cache-update', function () {
  //清除掉最近一次更新文件的緩存
  exec('git diff --name-only HEAD~ HEAD', $output);
  foreach ($output as $file) {
    $path = base_path($file);
    opcache_invalidate($path, true);
  }
  dd('刷新完成');
});

總結(jié)

通過上面的三種策略,可以實(shí)現(xiàn) Opcache 緩存更新的目的,但是在流量高峰期或者大流量的服務(wù)端,每次更新緩存都是一件非常損耗資源的事情,Opcache在重建緩存時(shí),也不會(huì)禁止其他進(jìn)程讀取,因此就會(huì)造成反復(fù)新建緩存,因此想要達(dá)到最佳的性能調(diào)配:

  • 最好不要在高峰期清理緩存

  • 高峰期不要頻繁的更新代碼,清理緩存,會(huì)造成重復(fù)新建緩存

  • 如果需要更新,可以嘗試削弱服務(wù)端權(quán)重,實(shí)現(xiàn)逐個(gè)更新的目的。

  • 如果需要強(qiáng)制更新,盡量選擇手動(dòng)清除緩存的方式,來重建Opcache緩存,使代價(jià)最小化。

到此,關(guān)于“為什么PHP Opcache 緩存刷新不了、代碼重載而且無法更新代碼”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI