free數據的來源
# 注意不同版本的free輸出可能會有所不同
# centos7版本
[root@local_sa_192-168-1-6 ~]# free
total used free shared buff/cache available
Mem: 8169348 263524 6875352 668 1030472 7611064
Swap: 0 0 0
Buffer和Cache不太好區分
Buffer是緩沖區,而Cache是緩存,兩者都是數據在內存中的臨時存儲
用man命令查詢free的文檔,就可以找到對應指標的詳細說明
buffers
Memory used by kernel buffers (Buffers in /proc/meminfo)
cache
Memory used by the page cache and slabs (Cached and SReclaimable in /proc/
buff/cache
Sum of buffers and cache
Buffers是內核緩沖區用到的內存,對應的是/proc/meminfo中的Buffers值
Cache是內核頁緩存和Slab用到的內存,對應的是/proc/meminfo中的Cached與SReclaimable之和
proc文件系統
/proc是Linux內核提供的一種特殊文件系統,是用戶跟內核交互的接口
用戶可以從/proc中查詢內核的運行狀態和配置選項, 查詢進程的運行狀態、統計數據等
也可以通過/proc來修改內核的配置
proc文件系統同時也是很多性能工具的最終數據來源
比如free ,就是通過讀取/proc/meminfo ,得到內存的使用情況
執行man proc,可以得到proc文件系統的詳細文檔
Buffers %lu
Relatively temporary storage for raw disk blocks that shouldn't get tremendously lar
Cached %lu
In-memory cache for files read from the disk (the page cache). Doesn't include SwapC
...
SReclaimable %lu (since Linux 2.6.19)
Part of Slab, that might be reclaimed, such as caches.
SUnreclaim %lu (since Linux 2.6.19)
Part of Slab, that cannot be reclaimed on memory pressure.
通過這個文檔,可以看到
- Buffers是對原始磁盤塊的臨時存儲,也就是用來緩存磁盤的數據,通常不會特別大 (20MB 左右)
這樣,內核就可以把分散的寫集中起來,統一優化磁盤的寫入,比如可以把多次小的寫合並成單次大的寫等等 - Cached是從磁盤讀取文件的頁緩存,也就是用來緩存從文件讀取的數據
這樣,下次訪問這些文件數據時,就可以直接從內存中快速獲取,而不需要再次訪問緩慢的磁盤 - SReclaimable是Slab的一部分。Slab包括兩部分,其中的可回收部分,用SReclaimable 記錄
而不可回收部分,用SUnreclaim 記錄
產生的疑問:
- Buffer的文檔沒有提到這是磁盤讀數據還是寫數據的緩存,而在很多網絡搜索的結果中都會提到Buffer只是對將要寫入磁盤數據的緩存。
那反過來說,它會不會也緩存從磁盤中讀取的數據呢? - Cache是對從文件讀取數據的緩存,那么它是不是也會緩存寫文件的數據呢?
案例
准備
實驗環境
# 服務端(192.168.1.6)
配置:2CPU,4G內存,centos7.6_64
預先安裝docker、sysstat、等工具(yum install sysstat -y)
為了減少緩存的影響,運行下面的命令來清理系統緩存:
# 清理文件頁、目錄項、Inodes 等各種緩存
[root@local_sa_192-168-1-6 ~]# echo 3 > /proc/sys/vm/drop_caches
這里的/proc/sys/vm/drop_caches,就是通過proc文件系統修改內核行為的一個示例,
寫入3表示清理文件頁、目錄項、Inodes等各種緩存。
場景 1:磁盤和文件寫案例
文件寫的案例
-
在第一個終端,運行 vmstat 命令
[root@local_sa_192-168-1-6 ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 3030208 12 318020 0 0 0 0 7 5 0 0 100 0 0 0 0 0 3030208 12 318020 0 0 0 0 61 102 0 0 100 0 0 0 0 0 3030208 12 318020 0 0 0 0 75 107 1 0 99 0 0 0 0 0 3030208 12 318020 0 0 0 0 37 69 0 0 100 0 0 0 0 0 3030208 12 318020 0 0 0 0 46 75 0 0 100 0 0
buff和cache就是前面看到的Buffers和Cache,單位是KB
bi和bo則分別表示塊設備讀取和寫入的大小,單位為塊 / 秒。因為Linux中塊的大小是1KB,所以這個單位也就等價於KB/s
正常情況下,空閑系統中,這幾個值在多次結果中一直保持不變
-
到第二個終端執行dd命令,通過讀取隨機設備,生成一個500MB大小的文件
[root@local_sa_192-168-1-6 ~]# dd if=/dev/urandom of=/tmp/file bs=1M count=500 記錄了500+0 的讀入 記錄了500+0 的寫出 524288000字節(524 MB)已復制,2.05113 秒,256 MB/秒
同時,觀察第一個終端,觀察Buffer和Cache的變化情況
[root@local_sa_192-168-1-6 ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 3023392 12 318244 0 0 0 0 63 114 0 0 99 0 0 1 0 0 3000776 12 340384 0 0 76 0 216 187 0 5 94 1 0 1 0 0 2743380 12 597688 0 0 0 0 1067 118 0 50 50 0 0 0 1 0 2496184 12 845864 0 0 0 97796 1402 415 0 48 8 41 2 0 1 0 2496264 12 845832 0 0 0 32768 179 118 0 1 50 49 0 0 1 0 2496296 12 845800 0 0 0 16384 122 117 0 0 50 50 0 0 1 0 2496168 12 845932 0 0 0 49152 248 90 0 1 50 49 0 0 0 0 2496712 12 845340 0 0 0 16896 256 102 0 1 83 16 0
通過觀察vmstat的輸出,我們發現,在dd命令運行時, Cache在不停地增長,而Buffer基本保持不變
再進一步觀察 I/O 的情況
- 在Cache剛開始增長時,塊設備I/O很少,bi只出現了一次76KB/s
而過一段時間后,才會出現大量的塊設備寫,比如bo變成了 97796 - 當dd命令結束后,Cache不再增長,但塊設備寫還會持續一段時間
並且,多次 I/O 寫的結果加起來,才是dd要寫的500M的數據
Cache 對文件的寫入會緩存
- 在Cache剛開始增長時,塊設備I/O很少,bi只出現了一次76KB/s
磁盤寫的案例
注意:下面的命令對環境要求很高,需要系統配置多塊磁盤,並且磁盤分區/dev/sdb1還要處於未使用狀態
如果只有一塊磁盤,千萬不要嘗試,否則將會對你的磁盤分區造成損壞
清理緩存后,向磁盤分區/dev/sdb1寫入2GB的隨機數據
# 首先清理緩存
[root@local_sa_192-168-1-6 ~]# echo 3 > /proc/sys/vm/drop_caches
# 然后運行 dd 命令向磁盤分區 /dev/sdb1 寫入 2G 數據
[root@local_sa_192-168-1-6 ~]# dd if=/dev/urandom of=/dev/sdb1 bs=1M count=2048
同時,觀察內存和I/O的變化情況
[root@local_sa_192-168-1-6 ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 7584780 153592 97436 0 0 684 0 31 423 1 48 50 2 0
1 0 0 7418580 315384 101668 0 0 0 0 32 144 0 50 50 0 0
1 0 0 7253664 475844 106208 0 0 0 0 20 137 0 50 50 0 0
1 0 0 7093352 631800 110520 0 0 0 0 23 223 0 50 50 0 0
1 1 0 6930056 790520 114980 0 0 0 12804 23 168 0 50 42 9 0
1 0 0 6757204 949240 119396 0 0 0 183804 24 191 0 53 26 21 0
1 1 0 6591516 1107960 123840 0 0 0 77316 22 232 0 52 16 33 0
從這里可以看到,雖然同是寫數據,寫磁盤跟寫文件的現象還是不同的
寫磁盤時(也就是bo大於0時),Buffer和Cache都在增長,但顯然Buffer的增長快得多
這說明,寫磁盤用到了大量的Buffer。
小結
對比兩個案例,可以知道,寫文件時會用到Cache緩存數據,而寫磁盤則會用到Buffer來緩存數據
所以,雖然文檔上只提到,Cache是文件讀的緩存,但實際上,Cache也會緩存寫文件時的數據
場景 2:磁盤和文件讀案例
文件讀的案例
清理緩存后,從文件/tmp/file中,讀取數據寫入空設備
# 首先清理緩存
[root@local_sa_192-168-1-6 ~]# echo 3 > /proc/sys/vm/drop_caches
# 運行 dd 命令讀取文件數據
[root@local_sa_192-168-1-6 ~]# dd if=/tmp/file of=/dev/null
然后,觀察內存和 I/O 的變化情況
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 1 0 7724164 2380 110844 0 0 16576 0 62 360 2 2 76 21 0
0 1 0 7691544 2380 143472 0 0 32640 0 46 439 1 3 50 46 0
0 1 0 7658736 2380 176204 0 0 32640 0 54 407 1 4 50 46 0
0 1 0 7626052 2380 208908 0 0 32640 40 44 422 2 2 50 46 0
觀察vmstat的輸出,發現讀取文件時(也就是 bi 大於 0 時),Buffer保持不變
而Cache則在不停增長。這跟查到的定義“Cache 是對文件讀的頁緩存”是一致的
磁盤讀的案例
清理緩存后,從磁盤分區/dev/sda1中讀取數 據,寫入空設備
# 首先清理緩存
[root@local_sa_192-168-1-6 ~]# echo 3 > /proc/sys/vm/drop_caches
# 運行 dd 命令讀取文件
[root@local_sa_192-168-1-6 ~]# dd if=/dev/sda1 of=/dev/null bs=1M count=1024
然后,觀察內存和 I/O 的變化情況
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 7225880 2716 608184 0 0 0 0 48 159 0 0 100 0 0
0 1 0 7199420 28644 608228 0 0 25928 0 60 252 0 1 65 35 0
0 1 0 7167092 60900 608312 0 0 32256 0 54 269 0 1 50 49 0
0 1 0 7134416 93572 608376 0 0 32672 0 53 253 0 0 51 49 0
0 1 0 7101484 126320 608480 0 0 32748 0 80 414 0 1 50 49 0
觀察vmstat的輸出,發現讀磁盤時(也就是 bi 大於 0 時),Buffer和Cache都在增長,但顯然Buffer的增長快很多
這說明讀磁盤時,數據緩存到了Buffer中
結論
Buffer 既可以用作“將要寫入磁盤數據的緩存”,也可以用作“從磁盤讀取數據的緩存”
Cache 既可以用作“從文件讀取數據的頁緩存”,也可以用作“寫文件的頁緩存”
Buffer是對磁盤數據的緩存,而Cache是文件數據的緩存,它們既會用在讀請求中,也會用在寫請求中
小結
Buffer 和 Cache 分別緩存磁盤和文件系統的讀寫數據
- 從寫的角度來說,不僅可以優化磁盤和文件的寫入,對應用程序也有好處,應用程序可以在數據真正落盤前,就返回去做其他工作
- 從讀的角度來說,既可以加速讀取那些需要頻繁訪問的數據,也降低了頻繁 I/O 對磁盤的壓力