- 摩傑斯
- 2026-10-29
Linux 伺服器慢怎麼排查?先分清六種「慢」,再加配置
在 Linux 伺服器上,運維接到"伺服器慢"的報障,直接動手查是錯的。原因很簡單:這句話裡沒有可以查的東西。
"慢"至少要先補三句:誰覺得慢、慢在哪一段、什麼條件下慢。補完這三句,多數情況能直接跳到某一兩種形態上,而不是從"加記憶體"開始一個個試。
這篇把六種"慢"分開講:各自的訊號、怎麼拿證據、處置方向,以及最常見的誤判。六種形態裡,只有第一種是 CPU 真的在算,其餘五種都不該用"加配置"來解決。
![]()
一、先把"慢"拆成三句
第一句,誰覺得慢。是操作的人在瀏覽器裡點一下要等三秒?是批次匯出報表跑了半小時?是每天八點半全廠同時開工單時卡?三種"慢"完全不是一個問題。前端互動慢,可能一秒都不在伺服器上——瀏覽器渲染、圖片載入、介面序列都算在裡面。
第二句,慢在哪一段。一次請求在 Linux 上至少經過四段:瀏覽器與網路、Web 服務與應用程式碼、資料庫、磁碟。定不到段,後面所有動作都是猜。
第三句,什麼條件下慢。一直慢、高峰慢、特定操作慢、跑一陣突然慢然後自己好——"時間形狀"不同,指向的原因幾乎不重疊。這一條最容易被忽略,但它往往一步就能把範圍砍掉一半。
二、形態一:CPU 真的在算
訊號:top 裡 %us(使用者態)高,load average 明顯超過核數,%wa 很低。
意味著:有東西在實打實消耗 CPU 週期。常見來源是計算密集型任務(匯出、統計、圖片處理)、死迴圈或正則回溯、加密與壓縮、序列化大物件,以及最近上線的新程式碼。
top -H -p <pid> # 看哪個執行緒在吃 CPU
perf top -p <pid> # 看熱點函式(有符號時)
pidstat -u 1 5 # 按程序取樣,確認是不是它一直在吃
處置方向:先看是不是"該忙"。批次任務在跑、報表在導,那叫正常負載,最佳化方向是錯峰或限流;如果沒有任何業務動作卻持續滿載,才是異常,往死迴圈、正則回溯、快取擊穿方向查。
最常見的誤判:只看 load average。單核機器 load 2 已經過載,32 核機器 load 8 還很閒。load 必須和核數一起看,而且 load 包含等待 IO 的程序,它高不一定是 CPU 忙。
三、形態二:CPU 沒忙,在等磁碟
訊號:%wa(iowait)持續偏高,%us 不高,load average 也高。機器看起來"忙",但 CPU 大量時間在空轉等待。
vmstat 1 5 # 看 wa 列
iostat -x 1 5 # 看每塊盤的 await、r/s、w/s、%util
iotop -o # 看哪個程序在讀寫
一個容易忽略的關聯:海量小檔案會讓 IO 明顯變慢。目錄裡堆了幾十萬個檔案時,讀一個檔案的元資訊都可能觸發多次定址,iostat 上表現為大量小 IO、await 升高。這類"慢"的根因在檔案數量,不在磁碟效能——清理檔案數量比換更快的盤有效得多。
處置方向:先分清是"讀多"還是"寫多"、是順序還是隨機。日誌同步寫、資料庫頻繁 fsync、備份任務與業務搶 IO,是三個高發場景。備份要限速、錯峰;日誌要非同步或調低刷盤頻率(前提是能接受少量丟失)。
四、形態三:記憶體不夠,開始換頁
訊號:vmstat 的 si/so 不為零(有實際換入換出),free 的 available 很低,dmesg 裡出現 OOM 記錄。
一旦開始換頁,延遲不是"慢一點",是數量級的惡化——一次換頁把微秒級的記憶體訪問變成毫秒級的磁碟訪問。
free -m # 看 available,不是看 free
vmstat 1 5 # si/so 是否持續非零
dmesg | grep -i oom # 有沒有程序被 OOM killer 幹掉
最常見的誤判:把 buff/cache 當成"被佔用的記憶體"。Linux 會主動用空閒記憶體做檔案快取,需要時回收,free 一列很低是正常的。判據是 available,它才是"還能給新程序用多少"。
處置方向:先找誰在漲(ps aux --sort=-rss),再看是快取無上限、連線池過大,還是業務量真的漲了。加記憶體能緩解,但如果根因是記憶體洩漏或快取無上限,加多少都會被吃滿。
五、形態四:磁碟本身慢,或者配額用完了
訊號:iostat 裡 await(平均等待)明顯偏高、%util 接近 100,但 CPU 和記憶體都不緊張。
雲上尤其常見一個隱形原因——雲盤的 IOPS 與頻寬按規格給,突發額度用完之後掉回基線。表現是"上午很快,下午突然變慢,第二天又好了",看起來像玄學,實際是配額。
iostat -x 1 5
# 關注 r_await / w_await 是否幾十毫秒以上;%util 是否長期貼 100
關於 %util 的提醒:這個指標在 SSD、NVMe 和多佇列裝置上會騙人——單塊盤 %util 100% 不等於頻寬打滿,它只是"裝置佇列非空的時間比例"。看吞吐和 await 比看 %util 可靠。
處置方向:先確認是不是規格/配額問題(雲控制檯的監控曲線能直接看到上限),再確認是不是寫放大(小隨機寫、日誌刷盤過頻、資料庫頁大小與塊大小不匹配)。前者升規格或拆分,後者調引數或改寫入模式——兩種病,兩種藥。
六、形態五:不是慢,是在排隊
訊號:CPU 不高、IO 不高、記憶體夠,但請求就是慢;同時資料庫或應用裡能看到大量等待。
資源都夠,但請求在等鎖、等連線、等執行緒。"慢"真正的含義是"排在前面的還沒處理完"。三個高發排隊點:
資料庫鎖等待——長事務佔著行鎖,後面的全堵住。MySQL 看 information_schema.innodb_trx 與 SHOW ENGINE INNODB STATUS 的鎖等待段;PostgreSQL 看 pg_stat_activity 裡 wait_event_type = 'Lock' 的會話,pg_blocking_pids() 能直接找出阻塞者。
連線池打滿——應用側的最大連線數是硬上限,打滿之後新請求排隊等連線。表現是介面耗時穩定在一個"奇怪的量級"(比如剛好 3 秒、5 秒),因為那是連線池的等待超時。
應用執行緒池序列——一個耗時介面占滿工作執行緒,其他請求全排隊。日誌裡會看到大量請求"同時開始、同時結束"。
處置方向:找"最長的那筆事務"或"佔著連線不放的那個請求",而不是加機器。加機器對鎖等待幾乎無效——鎖在同一個資料庫例項上。
七、形態六:鏈路與上游
訊號:伺服器自身指標全綠,但使用者端慢;或者伺服器出網請求慢。問題在伺服器之外。
頻寬打滿——出網頻寬被備份、日誌外傳、大檔案下載佔滿,iftop 一眼能看出。丟包與重傳——ping 看不出問題但 TCP 重傳率高,用 ss -s 或 netstat -s | grep -i retrans。DNS 解析慢——每次外部請求都帶一次 DNS 超時,累積起來很可觀。TLS 握手開銷——短連線每次新建握手,RTT 高的鏈路上代價翻倍。上游依賴慢——第三方介面或內部另一個服務慢,把整條鏈路拖住,這類最容易誤判成"我們伺服器慢"。
處置方向:給每個外部依賴加耗時打點,把"我們的耗時"和"等待別人的耗時"分開記。沒有這層拆分,永遠在猜。
八、一張判據表
| 形態 | 一眼訊號 | 第一條命令 | 典型誤判 |
|---|---|---|---|
| CPU 真忙 | %us 高、%wa 低 | top / pidstat -u 1 | 只看 load 不看核數 |
| 等磁碟 | %wa 高、%us 低 | vmstat 1 / iostat -x 1 | 直接換更快的盤 |
| 記憶體換頁 | si/so 非零、available 低 | free -m / vmstat 1 | 把 cache 當佔用 |
| 磁碟/配額 | await 高、%util 貼頂 | iostat -x 1 / 雲監控 | 把 %util 當頻寬 |
| 排隊 | 資源都閒、請求慢 | 鎖等待檢視、連線池指標 | 加機器 |
| 鏈路/上游 | 本機全綠、使用者慢 | iftop / ss -s / 依賴打點 | 把等待當自身問題 |
表的用法:先按"哪個資源緊張"分流,再看"緊張的是不是真兇"。注意"資源都閒但請求慢"這一格,它最容易把人帶向加配置,實際大多是排隊。
九、慢的時間形狀,比瞬時數值更有資訊量
一直慢:從上線就慢,多半是設計問題——N+1 查詢、缺索引、序列呼叫、單執行緒處理。加資源只能緩解一時。
高峰慢:早上八點半、每月一號、定時任務時段。這是容量與錯峰問題:要麼限流排隊,要麼把批次任務挪開。
爬坡式變慢:一天比一天慢,重啟就好——典型的記憶體洩漏、連線未釋放、臨時檔案堆積、表資料量增長導致索引失效。
突然慢又自己好:雲盤突發額度、備份任務、鄰居噪音、上游抖動。這類要的是"能對上時間點"的證據,不是調參。
特定操作慢:只在這個報表、這批資料慢。往那條具體路徑上查,別在整機上找。
問一句"是哪種形狀",往往比看十個監控圖有效。
十、五個常見誤判
一,直接加記憶體。記憶體曲線高不等於記憶體不夠,available 才是判據。加記憶體對鎖等待、慢查詢、頻寬打滿完全無效,卻最常被當成第一反應。
二,直接換更強的機器。排隊類問題換機器通常無效(鎖在同一個庫、連線池在上游);設計類問題換機器只是把慢從 3 秒變 2 秒。
三,用 load average 判斷負載。它混了 CPU 與 IO 等待,且必須與核數對照。
四,把 %util 當磁碟效能上限。多佇列裝置上它會誤報,看 await 與吞吐更可靠。
五,先調核心引數。sysctl 裡那些網路與記憶體引數,絕大多數場景下不是瓶頸;沒定位就調,是把問題變成"調過之後不知道原來是什麼問題"。
十一、處置順序:先止血,再最佳化,最後防復發
第一層,止血。目標只有一個:讓業務先恢復可用。手段通常是限流、降級、錯峰、臨時擴容、關掉非核心的批次任務。這一步不追求找到根因。
第二層,最佳化。有了止血爭取的時間,再按判據表定位。最佳化之前先做一件事:留一份基線。當前的 QPS、P95 延遲、各資源水位、慢查詢 Top 10 存下來。沒有基線,最佳化完只能說"感覺快了",下次再慢也無法判斷是退步還是新問題。
第三層,防復發。把這次出問題的那個訊號做成告警。慢類故障最大的特點是可以提前看見——CPU 爬升、記憶體爬坡、磁碟 await 上升、慢查詢數量增長,都早於使用者報障。缺的往往不是資料,是"沒人看"。
不需要一上來就上全套監控。先有四項就夠:負載與 CPU 分佈、available 記憶體與 swap 活動、每塊盤的 await、關鍵介面的 P95。這四項能覆蓋絕大多數"慢"的分流,等有了具體問題再補細節指標。這套基礎觀測我們摩傑斯在交付環境搭建時會一併做掉,原因是它決定了後面每一次"慢"是能查清楚,還是隻能猜。




