理解和配置 Linux 下的 OOM Killer
最近有位 VPS 客戶抱怨 MySQL 無緣無故掛掉,還有位客戶抱怨 VPS 經常當機,登陸到終端看了一下,都是常見的 Out of memory 問題。這通常是因為某時刻應用程式大量請求記憶體導致系統記憶體不足造成的,這通常會觸發 Linux 核心裡的 Out of Memory (OOM) killer,OOM killer 會殺掉某個程式以騰出記憶體留給系統用,不致於讓系統立刻崩潰。如果檢查相關的日誌檔案(/var/log/messages)就會看到下面類似的 Out of memory: Kill process 資訊:
Linux 核心根據應用程式的要求分配記憶體,通常來說應用程式分配了記憶體但是並沒有實際全部使用,為了提高效能,這部分沒用的記憶體可以留作它用,這部分記憶體是屬於每個程式的,核心直接回收利用的話比較麻煩,所以核心採用一種過度分配記憶體(over-commit memory)的辦法來間接利用這部分 “空閒” 的記憶體,提高整體記憶體的使用效率。一般來說這樣做沒有問題,但當大多數應用程式都消耗完自己的記憶體的時候麻煩就來了,因為這些應用程式的記憶體需求加起來超出了實體記憶體(包括 swap)的容量,核心(OOM killer)必須殺掉一些程式才能騰出空間保障系統正常執行。用銀行的例子來講可能更容易懂一些,部分人取錢的時候銀行不怕,銀行有足夠的存款應付,當全國人民(或者絕大多數)都取錢而且每個人都想把自己錢取完的時候銀行的麻煩就來了,銀行實際上是沒有這麼多錢給大家取的。
核心檢測到系統記憶體不足、挑選並殺掉某個程式的過程可以參考核心原始碼 linux/mm/oom_kill.c,當系統記憶體不足的時候,out_of_memory() 被觸發,然後呼叫 select_bad_process() 選擇一個 “bad” 程式殺掉,如何判斷和選擇一個 “bad” 程式呢,總不能隨機選吧?挑選的過程由 oom_badness() 決定,挑選的演算法和想法都很簡單很樸實:最 bad 的那個程式就是那個最佔用記憶體的程式。
上面程式碼裡的註釋寫的很明白,理解了這個演算法我們就理解了為啥 MySQL 躺著也能中槍了,因為它的體積總是最大(一般來說它在系統上佔用記憶體最多),所以如果 Out of Memeory (OOM) 的話總是不幸第一個被 kill 掉。解決這個問題最簡單的辦法就是增加記憶體,或者想辦法優化 MySQL 使其佔用更少的記憶體,除了優化 MySQL 外還可以優化系統(優化 Debian 5,優化 CentOS 5.x),讓系統儘可能使用少的記憶體以便應用程式(如 MySQL) 能使用更多的記憶體,還有一個臨時的辦法就是調整核心引數,讓 MySQL 程式不容易被 OOM killer 發現。
配置 OOM killer
我們可以通過一些核心引數來調整 OOM killer 的行為,避免系統在那裡不停的殺程式。比如我們可以在觸發 OOM 後立刻觸發 kernel panic,kernel panic 10秒後自動重啟系統。
從上面的 oom_kill.c 程式碼裡可以看到 oom_badness() 給每個程式打分,根據 points 的高低來決定殺哪個程式,這個 points 可以根據 adj 調節,root 許可權的程式通常被認為很重要,不應該被輕易殺掉,所以打分的時候可以得到 3% 的優惠(adj -= 30; 分數越低越不容易被殺掉)。我們可以在使用者空間通過操作每個程式的 oom_adj 核心引數來決定哪些程式不這麼容易被 OOM killer 選中殺掉。比如,如果不想 MySQL 程式被輕易殺掉的話可以找到 MySQL 執行的程式號後,調整 oom_score_adj 為 -15(注意 points 越小越不容易被殺):
當然,如果需要的話可以完全關閉 OOM killer(不推薦用在生產環境):
找出最有可能被 OOM Killer 殺掉的程式
我們知道了在使用者空間可以通過操作每個程式的 oom_adj 核心引數來調整程式的分數,這個分數也可以通過 oom_score 這個核心引數看到,比如檢視程式號為981的 omm_score,這個分數被上面提到的 omm_score_adj 引數調整後(-15),就變成了3:
下面這個 bash 指令碼可用來列印當前系統上 oom_score 分數最高(最容易被 OOM Killer 殺掉)的程式:
相關文章
- oom killerOOM
- Linux核心引數overcommit_memory和OOM killer介紹LinuxMITOOM
- 資料庫異常崩潰的元凶--OOM killer資料庫OOM
- MongoDB觸發oom-killer的簡單處理(一)MongoDBOOM
- 深入理解JVM之OOMJVMOOM
- Linux 的 OOM 終結者LinuxOOM
- Linux OOM 機制LinuxOOM
- 理解linux的配置檔案(轉)Linux
- Linux下FTP和TFTP服務配置LinuxFTP
- 深入理解MongoDB(一)Linux下配置MongoDB全攻略MongoDBLinux
- 理解linux配置檔案Linux
- CentOS 配置OOM監控報警CentOSOOM
- linux下vncserver的配置LinuxVNCServer
- linux下nfs的配置LinuxNFS
- The Omnipotent Monster Killer
- Linux下常用監控cacti的安裝和配置Linux
- Linux下Mongodb安裝和啟動配置LinuxMongoDB
- NUMA架構下oracle的oom異常架構OracleOOM
- 理解Linux配置檔案(轉)Linux
- jmeter.bat配置(主要關於OOM)JMeterBATOOM
- Linux平臺下snmp服務的安裝和配置Linux
- 20 Killer Perl Programming Tips for Beginners on UNIX / Linux OSLinux
- Linux系統下CUDA和cuDNN環境配置LinuxDNN
- linux下配置javaLinuxJava
- linux下配置zookeeperLinux
- Linux 下配置 HugePagesLinux
- Linux下SVN配置Linux
- SSH linux下配置。Linux
- linux下ASM配置LinuxASM
- LINUX下配置JDKLinuxJDK
- LINUX下配置MYSQLLinuxMySql
- Linux CentOS 7 下 Redis 的配置LinuxCentOSRedis
- Linux下Redis的安裝配置LinuxRedis
- linux下發郵件的配置Linux
- Linux下ftp的安裝配置LinuxFTP
- Linux下SNMP的安裝配置Linux
- linux下配置好的快捷鍵Linux
- D. The Omnipotent Monster Killer