Linux内存cache占用过高分析和优化
1、什么是buffer/cache ?buffer/cache其实是作为服务器系统的文件数据缓存使用的,尤其是针对进程对文件存在 read/write操作的时候,所以当你的服务进程在对文件进行读写的时候,Linux内核为了提高服务的读写速度,则将会把文件放在此处的 buffer/cache中进行缓存使用,由于Linux服务的特点便是任何事物都会以文件的形式进行存在,所以你会发现不管你是否对文件做了
1、什么是buffer/cache ?
buffer/cache 其实是作为服务器系统的文件数据缓存使用的,尤其是针对进程对文件存在 read/write 操作的时候,所以当你的服务进程在对文件进行读写的时候,Linux内核为了提高服务的读写速度,则将会把文件放在此处的 buffer/cache 中进行缓存使用,由于 Linux服务的特点便是任何事物都会以文件的形式进行存在,所以你会发现不管你是否对文件做了大规模的读写,机器的 buffer/cache 是一直都存在的,并且持续的增高不下,这是因为服务器所产生的网络连接也好,用户协议的(UDP)套接字也好,这部分的数据系统都会为应用程序创建对应的文件描述符,而这些文件描述符的使用,则又都会重新进入 buffer/cache 中做读写使用,所以这也是你的机器始终都会存在较高 buffer/cache 的原因,(因为所有的文件读写都会用到 buffer/cache,在内存合理的情况下)
2、buffer/cache 需要注意的一些特点
在服务内存够用的情况下,Linux内核为了加快对文件的读写效率会将文件放入之 buffer/cache 中 以保证读写效率,但其实,尽管当你的应用程序对文件的读写运行结束后,buffer/cache 也不会自动释放该部分内存,而是作为缓冲进行保留,等到你的服务进程在下一次进行相同文件的读写时就可以直接使用,省去了各种重新进行内存初始化的操作;所以这将会导致,当你的应用进程频繁对不同的文件进行读写时,你会发现服务所可以直接使用的free内存将会越来越少的一个重要原因;难道 buffer/cache 在这样无休止的缓存当中就不会自动释放?当然不是,当服务器在内存压力较大的情况下时,则将会自动进行内存的回收,作为free空间分给其它进程使用,这其中主要回收的一个内存则是 buffer/cache 的缓冲区内存块;
3、如何进行手动 buffer/cache 回收?
除了在系统进程内存使用较大压力的情况下进行内存的回收外,我们也可以进行手动的buffer/cache回收,但由于buffer/cache主要是用于文件的读写使用,所以进行文件回收时,一般常伴随系统的IO彪高,因为系统内核也对比cache中的数据与硬盘中的数据是否一致,如果不一致需要写会,然后才能进行内存的回收;
将内存中数据强制先刷新到磁盘中
sync;
清理Buffer缓存区域
echo 3 > /proc/sys/vm/drop_caches 表示清除pagecache和slab分配器中的缓存对象
echo 1 > /proc/sys/vm/drop_caches:表示清除pagecache。
echo 2 > /proc/sys/vm/drop_caches:表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的pagecache。
监控报警可用内存空间不足,常规的解决方案如下:
增加内存(增加成本)
增加虚拟内存(影响性能)
定期清理缓存(echo 1 > /proc/sys/vm/drop_caches)
问题分析
通过监控系统负载情况(vmstat 1),确定是页面缓存(cache项)占用量大,并且释放页面缓存后从块设备读入数据量(bi项)会马上增加。
通过监控io情况(iostat -x -k 1)也可以看出
基于此可以猜测是有进程在频繁的读取文件导致,监视磁盘I/O使用状况(iotop -oP),释放页面缓存后有几个sed命令读取文件进程占用IO很高。
生产环境遇到服务 buffer/cache 过高如何排查是由那几个进程引起的(hcache 的使用方式)
1、hcache的下载地址
hcache的github地址:https://github.com/silenceshell/hcache
hcache的下载地址:https://silenceshell-1255345740.cos.ap-shanghai.myqcloud.com/hcache
2、 hcache的使用方式
当前下载完对应的hcache后,则直接是一个对应的 bin文件,此时直接将对应的bin文件进行 chmod 授权后即可使用
将该bin文件设置为可执行文件
chmod 755 hcache
将该hcache移动到usr的bin目录中,使其可以被全局调用该命令
mv hcache /usr/local/bin/
3、hcache常用命令
全局显示10个最大的被缓存文件
hcache --top 10
| Name | Size (bytes) | Pages | Cached | Percent |
|-----------------------------------------------------------------------------------+----------------+-
| /app/java/jdk1.8.0_92/jre/lib/amd64/server/libjvm.so | 41943040 | 10240 | 8682 | 084.785 |
| libmergedlo.so | 101021431 | 24664 | 5858 | 023.751 |
| dockerd-current | 33398384 | 8154 | 3425 | 042.004 |
| libjvm.so | 16938578 | 4136 | 2429 | 058.728 |
| libjvm.so | 13363349 | 3263 | 1696 | 051.977 |
| docker-containerd-current | 10807760 | 2639 | 1171 | 044.373 |
查看指定进程ID所使用的buffer/cache 的使用情况
hcache -pid 16322
通过上述所获取到的被缓存最大的文件名称后,可以直接通过 lsof file_name 得到当前所开启该文件的所有进程信息;
显示使用 kbase-psrt.jar 的进程信息
[root@xiaoi-3614 ~]# lsof /app/kbase-psrt-wscc/kbase-psrt.jar
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 6048 root mem REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6048 root 5r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6048 root 6r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root mem REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root 5r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root 6r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
获取当前进程号所打开的所有文件信息
[root@xiaoi-3614 ~]# lsof -p 6048
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 6048 root cwd DIR 8,2 4096 136958862 /app/kbase-psrt-wscc
java 6048 root rtd DIR 8,2 4096 128 /
java 6048 root txt REG 8,2 7734 202909666 /app/java/jdk1.8.0_92/bin/java
java 6048 root mem REG 8,2 88776 203501791 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
java 6048 root mem REG 8,2 256702 135314838 /app/java/jdk1.8.0_92/jre/lib/amd64/libsunec.so
java 6048 root mem REG 8,2 106075056 2663 /usr/lib/locale/locale-archive
java 6048 root mem REG 8,2 93112 135314912 /app/java/jdk1.8.0_92/jre/lib/amd64/libnio.so
更多关于LSOF的使用,可以参考如下链接:
更多推荐
所有评论(0)