PHP 8 OPcache 調校完全指南:多站台 WordPress 命中率提升實戰 - Mr. 蔡大痣數位轉型顧問 - WordPress 及 SEO 專家

PHP 8 OPcache 調校完全指南:多站台 WordPress 命中率提升實戰

0 瀏覽
2026-05-04 更新

你有沒有開啟 OPcache 之後,命中率還是低於 10% 的經驗?這篇文章整理了我在管理多個 WordPress vhost 站台時,把 OPcache 命中率從不到 10% 調到穩定 99% 的完整過程,包含每個參數背後的邏輯、常見誤解(JIT 不是萬靈丹),以及多站台環境的記憶體分配策略。

OPcache 命中率是怎麼計算的

命中率的公式很直接:

命中率 = cache_hits ÷ (cache_hits + cache_misses) × 100%

每次 PHP 執行一個檔案,如果 bytecode 已經在記憶體裡,就算一次 hit;如果沒有(可能是第一次執行、被淘汰、或被判定為過期),就要重新編譯,算一次 miss。命中率偏低通常有三個原因:

  • 剛重啟 PHP-FPM:快取是空的,所有請求都是 miss,樣本數不夠,數字沒有意義
  • validate_timestamps = 1(預設值):每次請求都檢查檔案是否有變動,頻繁重驗導致 miss 增加
  • 記憶體不夠:快取滿了,舊的 bytecode 被 LRU 淘汰,下次又要重新編譯

最關鍵的設定:validate_timestamps

這是命中率最大的單一影響因素。預設值 validate_timestamps=1 代表每次 PHP 執行時都去檢查檔案的修改時間,確認快取還沒過期。對於生產環境來說,這個動作完全沒有必要,PHP 檔案不會在每次請求之間自動改變。

; 生產環境設定(PHP-FPM reload 後才重新掃描)
opcache.validate_timestamps=0
opcache.revalidate_freq=0

關掉之後,OPcache 只在 PHP-FPM reload 或 restart 時重新掃描檔案。部署新版本外掛或主題後,記得執行 systemctl reload php-fpm 讓快取更新。

⚠️ 開發機不要關這個,否則改了 PHP 檔案會看不到效果。

記憶體配置:單站台 vs 多 vhost 差很多

OPcache 是以 PHP-FPM 行程為單位共享快取的。每個站台的 PHP 檔案路徑不同,bytecode 全部分開儲存。以 WordPress 為例,一個站台的核心加上常見外掛大約佔 50~80 MB;10 個站台就需要 500~800 MB。

站台數建議 memory_consumption說明
1~3 個128 MB單站或小型多站,綽綽有餘
5~10 個512 MB中型多站環境標準值
10~20 個1024 MB大型多 vhost 環境
20 個以上1536~2048 MB建議同時監控 Free Memory

判斷記憶體是否足夠最直接的方式是看 Free Memory。如果 Free Memory 接近 0,代表快取空間被撐滿,LRU 淘汰正在發生,命中率會開始下降。

完整推薦設定值(PHP 8.2 生產環境)

以下是我實際使用在多 vhost WordPress 主機上的設定,可以直接參考:

; === OPcache 生產環境推薦設定(PHP 8.2)===

; 記憶體大小:依站台數調整
opcache.memory_consumption=1024

; 最大快取檔案數:用質數避免 hash collision
opcache.max_accelerated_files=65407

; 字串緩衝區:WPML 多語系站建議拉高
opcache.interned_strings_buffer=64

; 關掉檔案時間戳驗證(生產環境專用)
opcache.validate_timestamps=0
opcache.revalidate_freq=0

; JIT:WordPress 是 I/O 密集型,效益不大,建議關閉
opcache.jit=disable
opcache.jit_buffer_size=0

JIT 要不要開?WordPress 的答案

PHP 8 推出 JIT(Just-In-Time 編譯器)後,很多教學都建議開啟,但這個建議是針對 CPU 密集型應用設計的,例如大量數值計算、影像處理或自訂演算法。WordPress 的瓶頸在資料庫查詢、外部 API 呼叫與 hook 執行順序,不在 CPU 計算。

情境JIT 效益建議
WordPress 前台頁面載入幾乎無感(<3%)不值得開
WooCommerce 結帳流程可忽略不值得開
自訂 PHP 計算邏輯有感(10~30%)可以開
影像處理 / 報表產生顯著提升建議開

開啟 JIT 還要額外預占 jit_buffer_size 的記憶體(通常建議 64~128 MB),對多站台主機來說是額外成本。如果你的站台全是 WordPress,直接關閉 JIT,把那塊記憶體留給 OPcache 或 MySQL。

搭配 MySQL innodb_buffer_pool 一起調

OPcache 解決的是「PHP 編譯速度」的問題,但 WordPress 頁面慢,更多時候是 MySQL 的問題。innodb_buffer_pool_size 預設只有 128 MB,調高後 MySQL 把熱資料放在記憶體,不用一直讀磁碟,效果非常明顯。

先查 buffer pool 命中率,超過 99% 就不用動;低於 95% 代表記憶體不夠:

mysql -u root -p -e "
SELECT ROUND((1 - (
  SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_reads'
) / (
  SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_read_requests'
)) * 100, 2) AS buffer_pool_hit_rate_pct;"

如果你的伺服器有 16 GB RAM,建議這樣分配:

服務建議分配說明
OPcache1 GB10~20 個 WordPress vhost
MySQL innodb_buffer_pool4~6 GB依 DB 實際大小調整
PHP-FPM workers2 GB每 worker 約 40~80 MB
Nginx + 系統0.5 GB保留 headroom

更多 Rocky Linux LNMP 架構的調校細節,可以參考這篇:RockyLinux + PHP 8 安裝 PHP 擴充模組標準流程

如何監控 OPcache 狀態

用 PHP 直接查詢最快:

<?php
$status = opcache_get_status(false);
if ($status && $status['opcache_enabled']) {
    $stats = $status['opcache_statistics'];
    echo "命中率:" . round($stats['opcache_hit_rate'], 2) . "%\n";
    echo "Hits:" . number_format($stats['hits']) . "\n";
    echo "Misses:" . number_format($stats['misses']) . "\n";
    echo "已快取檔案數:" . $stats['num_cached_scripts'] . "\n";
    echo "已用記憶體:" . round($status['memory_usage']['used_memory'] / 1048576, 2) . " MB\n";
    echo "剩餘記憶體:" . round($status['memory_usage']['free_memory'] / 1048576, 2) . " MB\n";
}

看 Hits 和 Misses 的絕對數字比只看命中率百分比更有意義。如果 Hits 只有幾十筆,代表 PHP-FPM 剛重啟不久,樣本數太少,命中率偏低是正常的,等流量累積後再看。

常見問題 FAQ

OPcache 設定後要怎麼讓它生效?

修改 php.ini 後需要重啟或 reload PHP-FPM:systemctl reload php-fpm。如果使用 Apache,則重啟 Apache。設定生效後可用 opcache_get_status() 確認參數是否正確載入。

validate_timestamps=0 會不會讓外掛更新後沒效果?

會。關掉後 OPcache 不再自動偵測檔案變動,更新外掛或主題後需要手動執行 systemctl reload php-fpm(或呼叫 opcache_reset())讓快取更新。建議在部署流程中加上這個步驟。

多站台 vhost 要怎麼判斷 OPcache 記憶體夠不夠?

opcache_get_status() 裡的 memory_usage.free_memory,如果剩餘記憶體接近 0,代表快取空間已滿,LRU 淘汰正在發生,需要調高 opcache.memory_consumption。一般多站台環境每個 WordPress 站約佔 50~80 MB,10 個站台建議留 512 MB~1 GB。

PHP 8.2 的 JIT 到底要不要開?

對 WordPress 站台通常不建議。JIT 對 CPU 密集型運算有感,但 WordPress 的瓶頸在 DB 查詢與 I/O,JIT 幾乎不改善這類場景。開啟 JIT 還需要預占 jit_buffer_size 記憶體(建議至少 64 MB),對多 vhost 主機是額外負擔,效益比不上把記憶體留給 OPcache 或 MySQL。

命中率一直是 0% 或很低,是 OPcache 沒啟動嗎?

不一定。先確認 opcache_get_status()['opcache_enabled'] 是否為 true。若已啟動,命中率很低可能只是 PHP-FPM 剛重啟、快取是空的。等站台被訪問幾十次後再看 Hits 與 Misses 的絕對數字,若 Hits 已有幾百筆但命中率還低,才需要排查 validate_timestamps 設定。

▧ 文章分類

▧ 熱門文章

▧ 最新文章

✦ 虎鯨 OrcaBiz SEO 優化專業團隊 ✦

專業 SEO 公司幫助你將流量累積成看得見的業績,成為長期有效的最強業務!

[orca_infinite_scroll]