Skip to content

效能最佳化

店鋪訪問慢、後臺卡得要死?多半不是你網速差,也不是伺服器不行。

慢在哪

罪魁禍首是 PHP 的 session 檔案鎖。

Web 伺服器不是單執行緒跑你的 PHP 程式碼,而是多個工作程序同時處理請求。瀏覽器開啟一個頁面時,會並行去下載頁面裡引用的各種資源,於是同一個使用者瞬間就產生了好幾個併發請求。

而 PHP 的 session_start()阻塞,一直等到上一個請求的指令碼呼叫 session_write_close() 釋放為止。在 Linux 上它靠 flock() 實現。

結果就是:本來能並行的請求,被 session 鎖排成了一隊,一個接一個地跑。頁面上資源越多,感覺越卡。

這個鎖是必須的 —— 沒有它,多個程序同時讀寫同一份 session 資料會互相覆蓋,登入狀態就會莫名其妙丟失。問題不在於有鎖,而在於鎖的介質是檔案。

解決辦法:把 session 換成 Redis

只要三步,效果立竿見影。

1. 裝 Redis

寶塔使用者:軟體商店 → 搜尋 redis → 安裝。

其他環境按自己系統的方式裝即可。

2. 給 PHP 裝 redis 擴充套件

寶塔使用者:軟體商店 → 你的 PHP 版本 → 設定安裝擴充套件 → 選 redis 安裝。

3. 把 session 儲存改成 Redis

寶塔使用者: PHP 管理介面 → Session 配置 → 儲存模式改成 redis → 儲存。

沒有面板: 編輯 php.ini

ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

; 如果 Redis 設了密碼,用下面這行替代上面那行
; session.save_path = "tcp://127.0.0.1:6379?auth=你的redis密碼"

改完重啟 PHP,然後開啟你的店鋪 —— 差別會非常明顯。

Docker 使用者

映像裡已經帶了 Redis,不用做任何配置,開箱就是 Redis 會話。

接的是外部 Redis 的話,啟動容器時加上 -e ACG_REDIS_HOST=你的地址 即可,見 Docker 安裝

虛擬主機使用者

很遺憾,虛擬主機一般裝不了 Redis,也改不了 php.ini,這個最佳化用不上。

程式當初沒有強制用 Redis 做會話儲存,正是為了讓虛擬主機使用者也能跑起來。功能不受影響,只是快不起來。

還有一個坑:配置快取

如果某個配置項不在資料庫裡,程式每次請求都會去查一次庫、並且加排他鎖。在網路掛載(比如 CIFS)上,這會把全站請求序列化,比 session 鎖還慘。

現象是站點莫名其妙全域性變慢。遇到這種情況,檢查一下 runtime/config 是否完整。

不要手動刪 runtime/config 刪它會讓整站出問題。清模板快取只刪 runtime/view/compile

其他能做的

做法效果
開 opcachePHP 不用每次重新編譯,明顯提速
上 CDN靜態資源走 CDN,但注意配好真實 IP 獲取方式,否則拿到的全是 CDN 的 IP
定期清理訂單訂單表太大時後臺列表會變慢

基於 MIT 協議開源