Linux 系统缓存

linux系统为了增加系统的IO能力,会缓存磁盘的读写操作,将数据缓存在内存中。通过free命令可以看到系统的缓存信息

1
2
3
4

总计 已用 空闲 共享 缓冲/缓存 可用
内存: 15894 3817 7196 1120 4880 10747
交换: 9011 0 9011

包含写入缓存和读取缓存两个部分:

1
2
缓冲(buff)  : 写缓存
缓存(cache) : 读缓存

buff

因为硬盘写入的速度有限,为了避免程序卡顿和IO等待,有时候写入数据都是被临时写入到了系统内存(也可以强制存盘),然后等到IO不繁忙的时候写入到磁盘,这样的做法也有丢失数据的风险,linux下有手动同步数据到磁盘的命令:

1
sync

我就被这个问题坑过,在使用dd命令制作启动优盘的时候,一定要等待数据完全刷新到优盘在拔除优盘,否则启动盘会丢失数据,可以给dd命令加上写入磁盘的选项强制要求写入磁盘oflag=sync

1
sudo dd if=manjaro-xfce-20.0.3-200606-linux56.iso of=/dev/sdb4 bs=4M status=progress oflag=sync

同时,我们写程序的时候,写入文件结束以后记得调用flush来确保文件已经持久化成功。

cache

cache 是从磁盘读取文件时候的缓存,第一次读文件的时候因为内存种没有缓存这个文件,所以去读比较慢,当第二次读取的时候,已经有一部分缓存信息在内存中,这个时候速度会比较快,我们做个测试,读取一个大文件

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一次
hellojukay@local ~ $ time cat large_file >> /dev/null

real 0m10.221s
user 0m0.059s
sys 0m2.338s
# 第二次
hellojukay@local ~ $ time cat large_file >> /dev/null

real 0m1.451s
user 0m0.057s
sys 0m1.322s
hellojukay@local ~ $

可以看到第二次读取文件的速度明显加快了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
              总计         已用        空闲      共享    缓冲/缓存    可用
内存: 15894 2898 11334 490 1660 12317
交换: 9011 5 9005
# 第一次读取
[local hellojukay]# time cat large_file > /dev/null

real 1m26.948s
user 0m0.492s
sys 0m15.640s
[local hellojukay]# free
总计 已用 空闲 共享 缓冲/缓存 可用
内存: 15894 2761 4618 490 8514 12454
交换: 9011 5 9005
# 第二次读取
[local hellojukay]# time cat large_file > /dev/null

real 0m1.215s
user 0m0.030s
sys 0m1.184s
# 释放缓存
[local hellojukay]# echo 1 > /proc/sys/vm/drop_caches
# 第三次读取
[local hellojukay]# time cat large_file > /dev/null

real 1m28.599s
user 0m0.490s
sys 0m14.677s
# 第四次读取
[local hellojukay]# time cat large_file > /dev/null

real 0m1.225s
user 0m0.067s
sys 0m1.157s

可以看到第一次读取会自动缓存数据,后面再次读取速度就会加速,如果清理缓存以后,速度又会变慢。

缓存带来的问题

对于文件服务器或者代理服务来说可能会缓存数据比较量比较大,缓存占用了内存,导致系统的某些应用无法申请内存,造成OOM,解决这个问题有2种方式清理缓存

  • 配置 swap
  • 清理缓存

swap

当内存不够用的时候,系统会将缓存中的数据移动到 swap 中,释放出可用内存。

1
2
mkswap /dev/hda4 # 设置分为 swap 分区
swapon /dev/hda4 # 开启 swap

设置 swap 的大小也比较讲究,太小或者太大都不合适。

清理缓存

可以通过向系统内核写入配置来清理缓存

1
2
# 清理 cache
echo 1 > /proc/sys/vm/drop_caches

1
2
# 清理 buff
echo 2 > /proc/sys/vm/drop_caches
1
2
# 清理 cache 和 buff
echo 3 > /proc/sys/vm/drop_caches