前言
關於本章內容,設計的東西比較多。這里會有關於文件系統、磁盤、CPU等方面的知識,以及涉及到關於這方面的性能排查等。
術語
文件系統通過緩存和緩沖以及異步I/O等手段來緩和磁盤的延時對應用程序的影響。為了更詳細的了解文件系統,以下就簡單介紹一些相關術語:
- 文件系統:一種把數據組織成文件和目錄的存儲方式,提供了基於文件的存取接口,並通過文件權限控制訪問。另外,一些表示設備、套接字和管道的特殊文件類型,以及包含文件訪問時間戳的元數據。
- 文件系統緩存:主存(通常是DRAM) 的一塊區域,用來緩存文件系統的內容,可能包含各種數據和元數據。
- 操作:文件系統的操作是對文件系統的請求,包括讀、寫、打開、關閉、創建以及其他操作。
- I/O:輸入/輸出。文件系統I/O有多種定義,這里僅指直接讀寫(執行I/O)的操作,包括讀、寫、狀態統計、創建。I/O不包括打開文件和關閉文件。
- 邏輯I/O:由應用程序發給文件系統的I/O。
- 物理I/O:由文件系統直接發給磁盤的I/O。
- 吞吐量:當前應用程序和文件系統之間的數據傳輸率,單位是B/S。
- inode:一個索引節點時一種含有文件系統對象元數據的數據結構,其中有訪問權限、時間戳以及數據指針。
- VFS:虛擬文件系統,一個為了抽象與支持不同文件系統類型的內核接口。
磁盤相關術語:
- 存儲設備的模擬。在系統看來,這是一塊物理磁盤,但是,它可能由多塊磁盤組成。
- 傳輸總線:用來通信的物理總線,包括數據傳輸以及其他磁盤命令。
- 扇區:磁盤上的一個存儲塊,通常是512B的大小。
- I/O:對於磁盤,嚴格地說僅僅指讀、寫,而不包括其他磁盤命令。I/O至少由方向(讀或寫)、磁盤地址(位置)和大小(字節數)組成。
- 磁盤命令:除了讀寫之外,磁盤還會被指派執行其他非數據傳輸的命令(例如緩存寫回)。
- 帶寬:存儲傳輸或者控制器能夠達到的最大數據傳輸速率。
- I/O延時:一個I/O操作的執行時間,這個詞在操作系統領域廣泛使用,早已超出了設備層。
相關概念
文件系統延時
文件系統延時是文件系統性能一項主要的指標,指的是一個文件系統邏輯請求從開始到結束的時間。它包括消耗在文件系統、內核磁盤I/O子系統以及等待磁盤設備——物理I/O的時間。應用程序的線程通常在請求時阻塞,等地文件系統請求的結束。這種情況下,文件系統的延時與應用程序的性能直接和成正比關系。在某些情況下,應用程序並不受文件系統的直接影響,例如非阻塞I/O或者I/O由一個異步線程發起。
緩存
文件系統啟動之后會使用主存(RAM)當緩存以提供性能。緩存大小隨時間增長而操作系統的空余內存不斷減小,當應用程序需要更多內存時,內核應該迅速從文件系統緩存中釋放一些內存空間。文件系統用緩存(caching)提高讀性能,而用緩沖(buffering)提高寫性能。文件系統和塊設備子系統一般使用多種類型的緩存。
隨機I/O與順序I/O
一連串的文件系統邏輯I/O,按照每個I/O的文件偏移量,可以分為隨機I/O與順序I/O。順序I/O里每個I/O都開始於上一個I/O結束的地址。隨機I/O則找不出I/O之間的關系,偏移量隨機變化。隨機的文件系統負載也包括存取隨機的文件。由於存儲設備的某些性能特征的緣故,文件系統一直以來在磁盤上順序和連續的存放文件數據,以努力減小隨機I/O的數目。當文件系統未能達到這個目標時,文件的擺放變得雜亂無章,順序的邏輯I/O被分解成隨機的物理I/O,這種情況被稱為碎片化。
提示:關於文件系統更多內容,還請自行查閱相關理論。比如你還需要了解文件系統的預讀、預取、寫回緩存、同步寫、裸I/O、直接I/O、內存映射文件、元數據等相關知識。
性能分析
具備背景知識是分析性能問題時需要了解的。比如硬件 cache;再比如操作系統內核。應用程序的行為細節往往是和這些東西互相牽扯的,這些底層的東西會以意想不到的方式影響應用程序的性能,比如某些程序無法充分利用 cache,從而導致性能下降。比如不必要地調用過多的系統調用,造成頻繁的內核 / 用戶切換等。如果想深入了解Linux系統,建議購買相關書籍進行系統的學習。下面我們介紹如何分析磁盤性能工具(其實准確來說,不只是磁盤):
iostat
匯總了單個磁盤的統計信息,為磁盤負載、使用率和飽和度提供了指標。默認顯示一行系統總結信息,包括內核版本、主機名、日志、架構和CPU數量等,每個磁盤設備都占一行。
[root@localhost ~]# iostat Linux 3.10.0-514.el7.x86_64 (localhost.localdomain) 2017年09月18日 _x86_64_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.74 0.00 1.24 1.35 0.00 96.67 Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda 14.43 456.85 60.82 218580 29098 scd0 0.02 0.09 0.00 44 0 dm-0 13.65 404.58 56.50 193571 27030 dm-1 0.27 2.23 0.00 1068 0
參數說明
- tps: 每秒事物數(IOPS)。
- kB_read/s、kB_wrtn/s: 每秒讀取KB數和每秒寫入KB數。
- kB_read、kB_wrtn: 總共讀取和寫入的KB數。
如下想輸出更詳細的內容,可以試試下面這個命令組合:
[root@localhost ~]# iostat -xkdz 1 Linux 3.10.0-514.el7.x86_64 (localhost.localdomain) 2017年09月18日 _x86_64_ (1 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.01 2.43 13.81 2.32 510.51 67.96 71.74 0.22 13.94 8.72 44.95 2.37 3.82 scd0 0.00 0.00 0.03 0.00 0.10 0.00 8.00 0.00 0.27 0.27 0.00 0.27 0.00 dm-0 0.00 0.00 10.52 4.73 452.10 63.13 67.56 0.44 28.56 10.41 68.93 2.47 3.76 dm-1 0.00 0.00 0.30 0.00 2.49 0.00 16.69 0.00 1.50 1.50 0.00 1.38 0.04
參數說明
- rrqm/s:每秒合並放入驅動請求隊列的讀請求數(當系統調用需要讀取數據的時候,VFS將請求發到各個FS,如果FS發現不同的讀取請求讀取的是相同Block的數據,FS會將這個請求合並Merge)。
- wrqm/s:每秒合並放入驅動請求隊列的寫請求數。
- rsec/s:每秒發給磁盤設備的讀請求數。
- wsec/:每秒發給磁盤設備的寫請求數。
- rKB/s:每秒從磁盤設備讀取的KB數。
- wKB/s:每秒向磁盤設備寫入的KB數。
- avgrq-sz 平均每次請求大小,單位為扇區(512B)。
- avgqu-sz 在驅動請求隊列和在設備中活躍的平均請求數。
- await: 平均I/O響應時間,包括在驅動請求隊列里等待和設備的I/O響應時間(ms)。一般地系統I/O響應時間應該低於5ms,如果大於10ms就比較大了。這個時間包括了隊列時間和服務時間,也就是說,一般情況下,await大於svctm,它們的差值越小,則說明隊列時間越短,反之差值越大,隊列時間越長,說明系統出了問題。
- svctm:磁盤設備的I/O平均響應時間(ms)。如果svctm的值與await很接近,表示幾乎沒有I/O等待,磁盤性能很好,如果await的值遠高於svctm的值,則表示I/O隊列等待太長系統上運行的應用程序將變慢。
- %util: 設備忙處理I/O請求的百分比(使用率)。在統計時間內所有處理IO時間,除以總共統計時間。例如,如果統計間隔1秒,該設備有0.8秒在處理IO,而0.2秒閑置,那么該設備的%util = 0.8/1 = 80%,所以該參數暗示了設備的繁忙程度。一般地,如果該參數是100%表示設備已經接近滿負荷運行了(當然如果是多磁盤,即使%util是100%,因為磁盤的並發能力,所以磁盤使用未必就到了瓶頸)。
既然avgrq-sz是合並之后的數字,小尺寸(16個扇區或者更小)可以視為無法合並的實際I/O負載的跡象。大尺寸有可能是大I/O,或者是合並的連續負載。輸出性能里最重要的指標是await。如果應用程序和文件系統使用了降低寫延時的方法,w_await可能不那么重要,而更應該關注r_await。
對於資源使用和容量規划,%util仍然很重要,不過記住這只是繁忙度的一個度量(非空閑時間),對於后面有多塊磁盤支持的虛擬設備意義不大。可以通過施加負載更好地了解這些設備:IOPS(r/s + w/s)以及吞吐量(rkB/s + wkB/s)。
iotop
包含磁盤I/O的top工具。
批量模式(-b)可以提供滾動輸出。下面的演示僅僅顯示I/O進程(-o),每5秒輸出一次(-d5):
[root@localhost ~]# iotop -bod5
Total DISK READ : 0.00 B/s | Total DISK WRITE : 8.76 K/s Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 24.49 K/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND 21203 be/3 root 0.00 B/s 815.58 B/s 0.00 % 0.01 % [jbd2/dm-2-8] 22069 be/3 root 0.00 B/s 0.00 B/s 0.00 % 0.01 % [jbd2/dm-1-8] 1531 be/0 root 0.00 B/s 6.37 K/s 0.00 % 0.01 % [loop0] 3142 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.01 % [kworker/7:0] 21246 be/4 root 0.00 B/s 1631.15 B/s 0.00 % 0.00 % java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
提示:
輸出顯示java進程正在以大約1631.15 B/s的速率施加磁盤寫負載。其他有用的選項有-a,可以輸出累計I/O而不是一段時間內的平均值,選項-o,只打印那些正在執行的磁盤I/O的進程。
當然顯示磁盤的命令還有例如sar、iosnoop、perf、blktrace等命令,這里只列舉常用命令即可。
性能調優
文件系統優化
關於文件系統優化,並沒有太多的內容需要說明。就目前的情況,Redhat Enterprise 7系列默認更換為性能更好的XFS,這也是由於XFS在性能表現確實很好的原因。在我們使用的過程中,建議對XFS做一些簡單的優化即可,比如執行格式化時指定額外的一些參數,掛載該分區時指定一些額外的掛載參數,這些都能夠提高文件系統的相關性能。
格式化時的參數:
mkfs.xfs -d agcount=256 -l size=128m,lazy-count=1,version=2 /dev/diska1
mount時的參數:
defaults,noatime,nodiratime,nobarrier,discard,allocsize=256m,logbufs=8,attr2,logbsize=256k
磁盤相關優化
- 操作系統可調參數
包括ionice、資源控制和內核可調參數。
ionice
Linux中的ionice命令可以設置一個進程I/O調度級別和優先級。調度級別為整數,0表示無,不指定級別,內核會挑選一個默認值,優先級根據進程nice值選定;1表示實時,對磁盤的最高級別訪問,如果誤用會導致其他進程餓死;2表示盡力,默認調度級別,包括優先級 0~7,0為最高級;3表示空閑,在一段磁盤空閑的期限過后才允許進行I/O。如下:
ionice -c 3 -p 65552
cgroup
通過cgroup為進程或進程組提供存儲設備資源控制機制。一般很少用到,不用考慮。
可調參數
/sys/block/sda/queue/scheduler:選擇I/O調度器策略,是空操作、最后期限、an還是cfq;
- 磁盤設備可調參數
Linux上的hdparm(磁盤測試工具)工具可以設置多種磁盤設備的可調參數。
- 磁盤控制器可調參數