Linux

Linux内存指标中buffers和cached小结

一背景说明

我们在Linux系统上,通过free来查看系统内存资源使用情况时,会看到buffers和cache指标:

[root@localhost ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           7983        1436         802         625        5744        5632
Swap:          8063           0        8063
[root@localhost ~]# 

那么这两个指标分别表示什么呢?

二 实践验证

0 机器信息

[root@localhost ~]# uname -rm
3.10.0-514.el7.x86_64 x86_64
[root@localhost ~]# cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core) 
[root@localhost ~]# df -Th
文件系统            类型      容量  已用  可用 已用% 挂载点
/dev/mapper/cl-root xfs        50G   11G   40G   22% /
devtmpfs            devtmpfs  3.9G     0  3.9G    0% /dev
tmpfs               tmpfs     3.9G  4.0K  3.9G    1% /dev/shm
tmpfs               tmpfs     3.9G   25M  3.9G    1% /run
tmpfs               tmpfs     3.9G     0  3.9G    0% /sys/fs/cgroup
/dev/sdc1           xfs       200G   97G  104G   49% /pgdata
/dev/sdb5           xfs       100G   96G  4.5G   96% /pgdata2
/dev/sda1           xfs      1014M  121M  894M   12% /boot
/dev/mapper/cl-home xfs        42G   33G  8.2G   81% /home
tmpfs               tmpfs     799M     0  799M    0% /run/user/0
[root@localhost ~]# 

每次执行实践操作之前,我们都先把page cache、dentry、inode缓存清空。

[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches 
[root@localhost ~]# 

1 写文件操作

#terminal 1,执行下述操作
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches 
[root@localhost ~]# 
[root@localhost ~]# dd if=/dev/urandom of=/tmp/tempfile  bs=1M count=4000
​
记录了4000+0 的读入
记录了4000+0 的写出
4194304000字节(4.2 GB)已复制,331.938 秒,12.6 MB/秒
[root@localhost ~]# 
​
# 在另外一个terminal 2里,执行vmstat -SM 1 ,观察内存的使用变化情况
[root@localhost ~]# vmstat  -SM 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
22  0      0   5390      0    769    0    0    21   121   19   13 19  1 80  0  0
...
27  1      0   5305      0    825    0    0 22020    40 6846 1022 97  3  1  0  0
29  2      0   5262      0    859    0    0 24901    64 7938 1371 97  3  0  0  0
...
​

其中,dd if=/dev/urandom of=/tmp/tempfile bs=1M count=4000表示的是读取input file,每个块大小1M,一共4000个块,然后写出output file到/tmp/tempfile。

然后,我们可以看到vmstat的输出中,memory字段中的buffer并没有发生变化,这是cache字段随着时间推移,逐渐变大。同时,看到IO字段下的bo也跟着变大。

2 读文件操作

#terminal 1,执行下述操作
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches 
[root@localhost ~]# dd if=/tmp/tempfile bs=1M count=4000 of=/dev/null 
记录了4000+0 的读入
记录了4000+0 的写出
4194304000字节(4.2 GB)已复制,47.3821 秒,88.5 MB/秒
[root@localhost ~]#  
​
#terminal 2:执行vmstat -SM 1 ,观察内存的使用变化情况
[root@localhost ~]# vmstat  -SM 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 5  0      0   5811      0    741    0    0    25   126   15   18 19  1 80  0  0
 2  0      0   5810      0    741    0    0    16     0 4057  609 30  1 69  0  0
 4  0      0   5801      0    751    0    0  9784   104 6087 1500 39  2 52  7  0
 1  0      0   5790      0    762    0    0 11728   528 2797  759 20  2 78  1  0
 4  1      0   5723      0    847    0    0 86200    32 4226  637 38  3 49 11  0
 1  1      0   5636      0    934    0    0 89632    80 4341 1516 32  3 55 10  0
 6  1      0   5528      0   1043    0    0 111136    24 4619  646 41  3 46 10  0
 3  1      0   5419      0   1151    0    0 111584    80 4488 1014 33  3 55  9  0
42  2      0   5325      0   1247    0    0 96976   712 9514 3965 77  6 14  3  0
24  5      0   5246      0   1325    0    0 79360   930 10904 3283 95  4  1  0  0
 8  2      0   5139      0   1433    0    0 109924  1248 11521 4333 85  4  5  7  0
 3  1      0   5056      0   1517    0    0 85808   491 5589 1966 33  2 55 10  0
 3  2      0   4940      0   1632    0    0 118184   152 4171 3718 27  2 60 11  0
 1  1      0   4832      0   1739    0    0 109968   352 4522 3255 33  3 52 12  0
 3  1      0   4780      0   1792    0    0 53272   104 3849  588 36  1 53 10  0
 ...
 

这时,我们模拟从文件读出文件,并写出到系统黑洞/dev/null里,依然是写4G大小的数据。

这时,我们看到buff字段依然没有变化,同时cache不断增大,伴随着io字段的bi跟着变大。

这里的IO字段中的bi和bo分别表示block input,block output,其单位是KB,我们通过vmstat -SM 1表示的是每秒输出一次结果,也就意味着,bi和bo字段的值表示的是KB/s。

3 写磁盘操作

💊💊💊,这个操作要慎重,需要机器有除了操作系统之外,还有独立的磁盘。我这里有个独立的盘是/dev/sdb。因为该写入磁盘操作,会破坏磁盘中已有的数据。

#terminal 1,先清空缓存,然后执行写磁盘操作
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches 
[root@localhost ~]# dd if=/dev/urandom of=/dev/sdb5 bs=1M count=4000
记录了4000+0 的读入
记录了4000+0 的写出
4194304000字节(4.2 GB)已复制,371.912 秒,11.3 MB/秒
[root@localhost ~]# 
​
​
#terminal 2,监控内存和IO使用情况
[root@localhost ~]# vmstat -SM 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0   5791      0    796    0    0    28   128   18   18 19  1 80  0  0
 0  0      0   5791      0    796    0    0     0    76  394  227  3  0 97  0  0
 ...
 1  3      0   5468     93   1022    0    0 52064   432 8610 4376 23 15 49 14  0
 4  2      0   5431     99   1054    0    0 32760    24 10092 7159 10 16 56 18  0
 ...
 12  2      0    601   3736   2158    0    0     8 10416 10131 1632 19 14 49 18  0
 28  0      0    591   3747   2157    0    0     0 20968 8782 1803 64 12 21  3  0
 
#terminal 3,我们也可以通过free -m 来查看内存情况
[root@localhost ~]# free -m -w -s 1 -c 40
              total        used        free      shared     buffers       cache   available
Mem:           7983        1423        1665         624        2975        1920        5587
Swap:          8063           0        8063
...
              total        used        free      shared     buffers       cache   available
Mem:           7983        1510        1108         624        3308        2056        5497
Swap:          8063           0        8063
...
              total        used        free      shared     buffers       cache   available
Mem:           7983        1425         333         624        4000        2224        5585
Swap:          8063           0        8063
​
^C
[root@localhost ~]# 

此时,我们看到系统的cache字段变化不明显,反而buffers从0逐渐变大,直到变为4000M,和我们写入磁盘的数据大小一致结束。互相印证了。IO字段的bo逐渐变大。

4 读磁盘操作

#terminal 1,先清空缓存,然后执行读磁盘操作
[root@localhost ~]# echo 3 > /proc/sys/vm/drop_caches 
[root@localhost ~]# dd if=/dev/sdb
sdb   sdb1  sdb5  
[root@localhost ~]# dd if=/dev/sdb5  of=/dev/null bs=1M count=4000
记录了4000+0 的读入
记录了4000+0 的写出
4194304000字节(4.2 GB)已复制,41.243 秒,102 MB/秒
[root@localhost ~]# 
​
#terminal 2,监控内存和IO使用情况
[root@localhost ~]# vmstat -SM 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   5592      0    973    0    0    29   130   20   19 19  1 79  0  0
 0  0      0   5591      0    973    0    0   800   136 1028  471  7  0 92  0  0
 0  0      0   5591      0    974    0    0    16     0  485  328  0  0 99  0  0
 0  0      0   5589      0    976    0    0  1836  1400 7996 2061 72  2 26  0  0
 0  1      0   5540     46    977    0    0 47740   304  642  494  0  1 94  5  0
 0  1      0   5432    154    976    0    0 110600    96 1212  431  7  2 80 11  0
 ...
 1  1      0   2204   3262   1097    0    0 106504    96 1451  579  9  2 78 11  0
 0  1      0   2096   3370   1097    0    0 110852  2703 1331  996  4  2 83 11  0
 0  1      0   1996   3470   1097    0    0 102400   216 1106  447  7  1 80 11  0
 0  1      0   1935   3530   1097    0    0 61480    65  477  405  0  1 87 12  0
 0  1      0   1835   3630   1097    0    0 102480   843 1191  509  7  1 80 11  0
 4  2      0   1754   3710   1098    0    0 82832   176 1359  981  1  2 86 11  0
 0  1      0   1634   3830   1098    0    0 122880   792 7575 1664 69  2 23  5  0
 1  1      0   1535   3930   1098    0    0 102408   176  613  452  0  1 87 12  0
 0  0      0   1459   4006   1098    0    0 78012    64 1214  460  7  1 84  8  0
 1  0      0   1459   4006   1098    0    0     8    24  307  305  0  0 100  0  0

看到,读磁盘操作时,buffers从0逐渐增长到4000M,同时随着读磁盘操作完成之后,buffer不再变化。同时,看到IO字段的bi升高,bo变化不明显。

三 小结

1 内存指标中buffer和cache最终的含义

buffer用来缓存磁盘读、写数据的缓存;

cache用来缓存文件读、写数据的缓存;

2 磁盘读写和文件读写的区别

上述我们分别通过使用:

dd if=/dev/urandom of=/tmp/tempfile bs=1M count=4000;写/tmp/tempfile文件; free -m 结果中io字段的bo会跟着增加;

dd if=/tmp/tempfile of=/dev/null bs=1M count=4000;读/tmp/tempfile文件; free -m 结果中io字段的bi会跟着增加;

dd if=/dev/urandom of=/dev/sdb5 bs=1M count=4000;写磁盘分区;free -m 结果中io字段的bo会跟着增加;

dd if=/dev/sdb5 of=/dev/null bs=1M count=4000;读磁盘分区;free -m 结果中io字段的bi会跟着增加;

其中,当我们直接对磁盘、磁盘分区进行读写时,是绕过操作系统层面的,不走文件系统层面的缓存;这就如同Oracle数据库使用裸设备作为存储设备的场景一样;

当我们对磁盘上的文件进行读写时,它是要走操作系统层面的缓存的,需要经过文件系统层面。

3 认真读了man free命令的帮助信息

其中,收获的是:free -m -w -t 1 -c 40;

-m:表示的是以MB为单位输出结果;

-w:表示的以宽行格式分别显示buffers和cache字段的值;

-t:表示每秒输出1次结果;

-c:表示的累计输出40次;

如果加上-t的话,会在每次输出结果后面,再加一行total的信息。

[root@localhost ~]# free -m -w -t 1 -c 40 -t
              total        used        free      shared     buffers       cache   available
Mem:           7983        1440         800         625        3592        2148        5629
Swap:          8063           0        8063
Total:        16047        1440        8864
​
              total        used        free      shared     buffers       cache   available
Mem:           7983        1440         796         625        3592        2153        5629
Swap:          8063           0        8063
Total:        16047        1440        8860
​
^C
[root@localhost ~]# 

接下来,要继续认真读一下man proc; man ps; man top;

留言