聊聊伺服器的負載
負載可以說是一個伺服器是否正常的風向標,當接入的軟體執行緩慢的時候,相信大部分人排查線上伺服器第一件事就是要看下負載的高低?通過uptime命令可以直觀的看到系統1、5、15分鐘內的平均負載值,本文簡稱為負載。那麼關於負載就有一些有意思的話題了。如什麼是負載,如何判定負載的高低?那些原因導致負載升高?下面結合我的一些工作經驗簡單聊一聊。
什麼是負載?
在我最早接觸負載一詞的時候,大腦裡的印象就是衡量伺服器的繁忙程度,因此伺服器的負載不能太高,高了的話伺服器就忙不過來了。我對負載這樣的認識一直大概保持了一年半,後來還是因為有個原 因,於是去man了下uptime。
關於負載的解釋,uptime上有算是較為詳細的說明:
System load averages is the average number of processes that are either in a runnable or uninterruptable state. A process in a runnable state is either using the CPU or waiting to use the CPU. A process in uninterruptable state is waiting for some I/O access, eg waiting for disk. The averages are taken over the three time intervals. Load averages are not normalized for the number of CPUs in a system, so a load average of 1 means a single CPU system is loaded all the time while on a 4 CPU system it means it was idle 75% of the time.
根據以上的描述,負載的概念就清晰起來了,首先負載是什麼? 負載是一個平均程序數。那麼,是所有狀態下的程序數嗎?不是的,對程序的狀態有要求,就是程序的狀態需要處於 runnable state(可執行狀態) 和 uninterrupttable state(不可中斷狀態)。
ok,現在的重點來到了這兩種狀態的程序的理解上,何為 runnable 狀態,上面也給出了清晰的解釋,就是要麼程序正在使用cpu,要麼正在等待著使用cpu。對這句解釋稍作補充,在一個程序的生命週期中,會有不同狀態,處於runnable狀態的程序代表著一切資源準備就緒了(cpu資源除外),那麼就會有兩種情況,一種是已經獲得了cpu資源的,那麼就代表著他正在使用cpu資源進行執行,另外一種就是他在排隊等待cpu資源。(程序排程器會為使用cpu資源的程序維護一個佇列)因為linux是多使用者多程序系統,程序數量一般遠大於cpu數量,因此cpu的資源是珍貴的,使用需要申請和排隊。
何為uninterruptable 狀態?,就是程序正在等待一些IO的請求,諸如磁碟IO/網路IO。說實在的,對於這個理解我還只能停留在表面。uninterruptable和 interruptable都是程序的sleep狀態。我們可以理解為程序在睡覺(程序要繼續執行的條件和資源不充分,因此他們要睡覺),進入這兩種狀態下,他們會立即釋放掉cpu資源,不同點在於,處於interruptable是一種淺睡,任何的風吹草動(訊號)都會驚醒他,然後他就會醒來接著幹活。那麼uninterruptable 就是一種沉睡,只有他等到的東西等來了他才醒來。
總結來說,負載數值即是處於runnable state 和uninterruptable state 的程序數。可以大致理解為系統正在處理的程序數。
如何判斷負載的高低?
記得畢業後剛入職幾個月的時候,適逢雙十一,上面分了幾臺小的伺服器,讓盯梢負載。然後,我問旭哥說多高負載算高,旭哥說超過1就很高了。所以,從此我就記住了,負載高於1就高了。直到有一次一個持有相同概念的同事被另外一個同事鄙視後,我偷偷弄明白了負載後,負載高於1就過載的說法就不攻自破了。
關於負載過1就過載的說法在只有一個cpu的情況下是可以理解的,因為一個cpu同一時刻只能處理一個程序,所以剛好是100%的滿負荷執行。但是在一個四核的機器上,無異於其他三個cpu在空閒著。所以看負載是否過載,要有一個前提,那就是需要明確有幾個cpu,如果負載數長時間高於cpu數,那麼就可以判斷為過載。
cat /proc/cpuinfo
以上命令可以檢視cpu的個數。但這並不是說,我們都要線上的機器都要滿負荷的去跑,肯定是要有一定的餘量的,至於餘多少,可以根據自己業務的訪問情況決定。
那些原因導致負載升高?
有了對負載本質的瞭解,就不難分析出負載較高的情況了?導致負載升高的原因無非有兩個原因,一個是處於 runnable state 的程序不斷增多,另一個是處於 uninterruptable state的程序不斷增多。runnable state 增多一般是cpu資源不夠,而uninterruptable state增多大部分時間是磁碟IO成為瓶頸。
cpu資源不夠,為了方便理解,我們可以假設機器只有一個cpu,而每個程序處理需要1s,但是每1s就會2個程序需要處理,此時每1過1s就會累積一個程序處理不掉,那麼負載自然就不斷的增加
IO成為瓶頸,有的時候cpu利用率不是很高,但是負載依然會很高,比如大量的讀請求,導致磁碟io成為瓶頸,此時程序在等待磁碟IO的同時是不可中斷的狀態,因此仍然會參與負載值的計算,因此負載會變高
個人遇到的一些導致負載升高的原因
本人從事電商ERP系統開發,伺服器中安裝有mysql伺服器,因此一般情況下,出問題大部分是mysql中的一些問題。
- 大量資料請求時,包括搜尋時全表掃描、以及大量的匯出資料等。這種情況下一般大量的讀請求讓IO成為瓶頸,導致其他程序也處理緩慢,因此隨著時間的增加負載就會升高
- 事務未提交,一般一些業務處理系統,耦合關係強,如訂單的出庫和庫存的關係,一般是需要原子性操作,這個時候一般會使用事務來進行控制,但是不幸出現事務未提交的情況,會導致大量資源被鎖,其他請求處於長時間等待的情況,這種情況也會導致負載升高
- 死鎖,mysql的死鎖檢測以及回滾都會有一定的時間,加之事務對資源的獨佔,出現死鎖會出現短暫的擁堵現象,同時負載的短時間內上升,不過後面繼續會下降。但是死鎖很頻繁的情況下,負載也會一直較高
-
記憶體不足時,mysql伺服器是相當耗費記憶體的,如果記憶體不足導致交換分割槽長時間使用的話,也會讓機器負載升高
其他導致的一些IO問題,如磁碟損壞以及磁碟空間不足