案例十八、找出磁盤IO忙的真兇

計算機有三大件:CPU、內存、磁盤,這三者有一個拖後腿的,那就是磁盤。在生產環境,作爲數據庫角色的服務器磁盤建議拿至少4塊硬盤做Raid10,這樣既保證數據讀寫速度也保證數據的安全。如果使用普通的磁盤,即使CPU再強悍,最終的服務器性能也不會太好。

經常有遇到因爲磁盤I/O效率低而導致MySQL查詢非常慢的問題。對於一般的小網站來說,MySQL的查詢隊列不會超過100個,甚至不會超過10個,這是因爲MySQL查詢速度非常快。如果查詢隊列數量突然變大,可能是因爲網站訪問量變大也可能是因爲磁盤讀寫速度變慢。

本案例的背景是,一臺阿里雲機器,收到告警磁盤IO達到100%,但是登錄機器後查看並沒有什麼異常,也就是說磁盤飆到100%只是短暫的一會兒。既然出現了100%的情況,那說明肯定是有某個進程有問題。由於這個問題並不是一直出現,所以排查起來有點困難。於是,想到寫一個監測腳本,來實時查看磁盤IO使用情況,當發現異常時,則通過一些查看服務器狀態的指令來記錄具體的指標,從而分析出是什麼造成的磁盤IO使用率100%。


知識點一:使用iostat查看磁盤IO

如果沒有iostat命令,需要安裝sysstat包。

iostat不加任何選項:

# iostat
Linux 3.10.0-693.el7.x86_64 (wbs) 	2019年08月20日 	_x86_64_	(2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.07    0.00    0.21    0.01    0.00   99.71

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.28         0.69         1.89     326317     891105
sdb               0.00         0.01         0.00       4332          0
scd0              0.00         0.00         0.00       1028          0
dm-0              0.00         0.00         0.00       1036          0

avg-cpu:爲總體CPU使用統計情況,對於多核CPU,這裏爲所有CPU的平均值。

Device:爲各磁盤設備的io統計信息。


對於CPU統計信息一行,我們主要看iowait的值,它指示CPU用於等待io請求完成的時間。

Device中各列含義如下:

Device:設備名稱
tps:每秒進程下發的IO讀、寫請求數量
Blk_read/s:每秒讀扇區數量(一扇區爲512bytes)
Blk_wrtn/s:每秒寫扇區數量
Blk_read:取樣時間間隔內讀扇區總數量
Blk_wrtn:取樣時間間隔內寫扇區總數量

我們經常會在iostat後加上兩字數字,如:

# iostat 1 3

表示每隔1秒打印1次,共打印3次。iostat命令還有一個非常實用的選項-x,它可以顯示更多的信息,也是一個最常用的選項:

# iostat -d -x 1 2
Linux 3.10.0-693.el7.x86_64 (wbs) 	2019年08月21日 	_x86_64_	(2 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.02    0.01    0.27     0.68     1.90    18.11     0.00    6.45   24.55    5.48   1.94   0.06
sdb               0.00     0.00    0.00    0.00     0.01     0.00    46.33     0.00    9.07    9.07    0.00   6.27   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00   114.22     0.00   51.11   51.11    0.00  30.56   0.00
dm-0              0.00     0.00    0.00    0.00     0.00     0.00    48.19     0.00    4.02    4.02    0.00   3.67   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

說明:-d選項可以把CPU相關信息過濾掉,只顯示磁盤相關信息,以下爲各列的含義:

rrqm/s:每秒對該設備的讀請求被合併次數,文件系統會對讀取同塊(block)的請求進行合併。
wrqm/s:每秒對該設備的寫請求被合併次數。
r/s:每秒完成的讀次數。
w/s:每秒完成的寫次數。
rkB/s:每秒讀數據量(kB爲單位)。
wkB/s:每秒寫數據量(kB爲單位)。
avgrq-sz:平均每次IO操作的數據量(扇區數爲單位)。
avgqu-sz:平均等待處理的IO請求隊列長度。
await:平均每次IO請求等待時間(包括等待時間和處理時間,毫秒爲單位)。
svctm:平均每次IO請求的處理時間(毫秒爲單位)。
%util:採用週期內用於IO操作的時間比率,即IO隊列非空的時間比率。

對於這些列,我們最應該關注的是%util,本案例中提到磁盤使用率100%,其實就是%util的值爲100%。


知識點二:iotop查看哪個進程磁盤讀寫最高

iotop命令是一個用來監視磁盤I/O使用狀況的top類工具。iotop具有與top相似的UI,其中包括PID、用戶、I/O、進程等相關信息。iotop命令就是由iotop包安裝得來的。

iotop結果顯示跟top類似,它是動態實時查看各個進程的磁盤讀寫情況,效果如下:

Total DISK READ :	0.00 B/s | Total DISK WRITE :       0.00 B/s
Actual DISK READ:	0.00 B/s | Actual DISK WRITE:       0.00 B/s
   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                               
 45078 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.09 % [kworker/0:0]
     1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % systemd --switched-root --system --deserialize 21
     2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
     3 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [ksoftirqd/0]
     5 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kworker/0:0H]
     7 rt/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [migration/0]
   520 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [xfs-data/sda1]
     9 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [rcu_sched]
    10 rt/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [watchdog/0]
    11 rt/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [watchdog/1]
    12 rt/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [migration/1]
    13 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [ksoftirqd/1]
   526 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [xfsaild/sda1]
    15 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kworker/1:0H]
   528 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kdmflush]
    17 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kdevtmpfs]
    18 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [netns]
    19 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [khungtaskd]
    20 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [writeback]
    21 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kintegrityd]
    22 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [bioset]
    23 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kblockd]
    24 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [md]
  1049 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % gssproxy -D
  1050 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % gssproxy -D
  1052 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % gssproxy -D
  1053 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % gssproxy -D

主要看第4列和第5列。iotop有幾個快捷鍵,如下:

左右方向鍵:改變排序方式,默認是按IO排序。

r:改變排序順序。

o:只顯示IO輸出的過程。

p:進程/線程的顯示方式的切換。

a:顯示累積使用量。

q:退出。


如果在shell腳本中使用iotop命令,需要加上-b選項,即靜態顯示的模式,還需要加另外幾個選項,具體用法如下:

# iotop -obn2
Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s
   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s
   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
 45078 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.09 % [kworker/0:0]

說明:-o跟上面那個快捷鍵o是一個意思,它的作用是隻顯示有IO的進程。-n2表示需要統計2次,因爲第一次不會顯示任何進程。


本案例參考腳本

#!/bin/bash
##監控磁盤IO使用率,並找出哪個進程造成磁盤使用率很高
##該腳本需要寫一個常駐循環
##作者:
##日期:

#判斷機器上是否安裝iostat命令
if ! which iostat &>/dev/null
then
    yum install -y sysstat
    #如果你的機器爲ubuntu,請使用這個命令:apt-get install -y sysstat
fi

#判斷機器上是否安裝iotop命令
if ! which iotop &>/dev/null
then
    yum install -y iotop
    #如果你的機器爲ubuntu,請使用這個命令:apt-get install -y iotop
fi

#定義記錄日誌的目錄
logdir=/tmp/iolog
[ -d $logdir ] || mkdir $logdir

#定義日誌名字
dt=`date +%F`

#定義獲取io的函數(取5次平均值)
get_io()
{    
    iostat -dx 1 5 > $logdir/iostat.log
    sum=0

    #取最後一列的%util值循環遍歷然後相加
    for ut in  `grep "^$1" $logdir/iostat.log|awk '{print $NF}'|cut -d. -f1`
    do
        sum=$[$sum+$ut]
    done
    echo $[$sum/5]
}

#這裏的true表示條件爲真
while true
do
    #獲取所有設備,對所有設備名遍歷
    for d in `iostat -dx|egrep -v '^$|Device:|CPU\)'|awk '{print $1}'`
    do
        io=`get_io $d`
        #如果io使用率大於等於80
        if [ $io -ge 80 ]
        then
            #向日志裏記錄時間、iostat和iotop信息
            date >> $logdir/$dt   
            cat $logdir/iostat.log >>$logdir/$dt
            iotop -obn2 >>$logdir/$dt
            echo "####################" >>$logdir/$dt
        fi
    #休眠10秒,繼續以上步驟
    done
    sleep 10
done


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章