记一次由于buff/cache导致服务器内存爆满的问题

打印 上一主题 下一主题

主题 799|帖子 799|积分 2397

目次


前言
复现
登录服务器查看占用内存历程排行
先了解一下什么是buff/cache?
尝试开释buffer/cache
/proc/sys/vm/drop_caches
dirty_ratio
dirty_background_ratio
dirty_writeback_centisecs
dirty_expire_centisecs
drop_caches
page-cluster
swapiness
vfs_cache_pressure




前言

我目前在使用pve作为我的虚拟化系统,我在pve中开了一个centos7作为我的mc服务器系统
我写了个定时使命使用python每天破晓3点将磁盘中的游戏数据备份到pve宿主机中的raid5阵列中,但是我发现服务器内存总是爆满,我开端判定是实行备份脚本导致的,背面实际测试后发现确实是

复现

我先手动触发一次备份 (配景备份)
  1. nohup python server.py &
复制代码
等待数据备份完成,在pve中查看服务器内存占用

发现服务器内存已经爆满了

登录服务器查看占用内存历程排行

  1. top -o %MEM
复制代码
  1. top - 18:09:07 up  9:45,  1 user,  load average: 0.84, 0.36, 0.19
  2. Tasks: 241 total,   2 running, 239 sleeping,   0 stopped,   0 zombie
  3. %Cpu(s):  4.1 us,  4.8 sy,  0.0 ni, 90.6 id,  0.5 wa,  0.0 hi,  0.0 si,  0.0 st
  4. KiB Mem : 41034536 total, 17324592 free,  7754368 used, 15955576 buff/cache
  5. KiB Swap:  3145724 total,  3135220 free,    10504 used. 32879168 avail Mem
  6.   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                     
  7. 10536 root      20   0   43.0g   6.1g  25104 S   4.5 15.6 111:50.22 java                                                                        
  8. 9140 polkitd   20   0 3191660 451248  21032 S   0.0  1.1   8:47.40 mysqld                                                                     
  9. 8882 root      20   0 2379512  69380  25784 S   0.0  0.2   0:44.79 dockerd                                                                     
  10.   872 root      20   0  920636  51408  18904 S   0.0  0.1   2:13.25 node                                                                        
  11.   848 root      20   0  936892  47088  18456 S   0.0  0.1   1:10.98 node                                                                        
  12. 8864 root      20   0 1440692  39356  14624 S   0.0  0.1   0:32.95 containerd                                                                  
  13. 8802 root      20   0  715916  30604   6252 S   0.0  0.1  19:44.84 nattunnel                                                                  
  14. 8734 root      20   0  723448  26208      4 S   9.1  0.1  51:22.65 frpc                                                                        
  15. 8745 root      20   0  723704  24916      4 S   0.0  0.1   2:59.84 frpc                                                                        
  16. 1122 root      20   0  574288  17340   6012 S   0.0  0.0   0:07.49 tuned                                                                       
  17. 10472 root      20   0 2089844  16204   1760 S   0.0  0.0   9:55.88 docker-proxy                                                               
  18. 9120 root      20   0  720048  13496   4356 S   0.0  0.0   0:04.49 containerd-shim                                                            
  19. 10517 root      20   0  720304  13184   4388 S   0.0  0.0   0:04.79 containerd-shim                                                            
  20.   842 polkitd   20   0  612240  11224   4764 S   0.0  0.0   0:00.39 polkitd                                                                     
  21.   869 root      20   0  626196  11216   6916 S   0.0  0.0   0:03.10 NetworkManager                                                              
  22. 10450 root      20   0 1489616   8076   1392 S   0.0  0.0   0:00.08 docker-proxy                                                               
  23. 8326 root      20   0  155288   7584   2368 R  72.7  0.0   1:15.53 python                                                                     
  24.     1 root      20   0  194064   7224   4232 S   0.0  0.0   0:16.54 systemd                                                                     
  25. 9098 root      20   0 1350604   6036   1392 S   0.0  0.0   0:00.21 docker-proxy                                                               
  26. 9104 root      20   0 1489872   6036   1392 S   0.0  0.0   0:00.08 docker-proxy                                                               
  27. 10457 root      20   0 1489872   6036   1396 S   0.0  0.0   0:00.08 docker-proxy                                                               
  28. 10479 root      20   0 1424080   6028   1384 S   0.0  0.0   0:00.07 docker-proxy                                                               
  29.   599 root      20   0   39056   5972   5648 S   0.0  0.0   0:01.44 systemd-journal                                                            
  30. 10494 root      20   0 1489872   5752   1152 S   0.0  0.0   0:00.07 docker-proxy                                                               
  31.   621 root      20   0  127396   5632   2604 S   0.0  0.0   0:00.05 lvmetad                                                                     
  32. 7435 root      20   0  154796   5496   4172 S   0.0  0.0   0:01.03 sshd                                                                        
  33.   635 root      20   0   48392   4864   2880 S   0.0  0.0   0:00.55 systemd-udevd                                                               
  34. 1123 root      20   0  113004   4376   3344 S   0.0  0.0   0:00.08 sshd                                                                        
  35. 1615 postfix   20   0   90088   4308   3260 S   0.0  0.0   0:00.12 qmgr                                                                        
  36. 3313 postfix   20   0   89912   4104   3092 S   0.0  0.0   0:00.06 pickup                                                                     
  37. 10501 root      20   0 1424080   3984   1392 S   0.0  0.0   0:00.07 docker-proxy                                                               
  38. 1125 root      20   0  216400   3856   3164 S   0.0  0.0   0:04.15 rsyslogd                                                                    
  39.   850 dbus      20   0   66452   2564   1880 S   0.0  0.0   0:01.13 dbus-daemon                                                                 
  40. 7446 root      20   0  115680   2292   1708 S   0.0  0.0   0:00.39 bash                                                                        
  41. 8436 root      20   0  162272   2272   1532 R  13.6  0.0   0:00.10 top                        
复制代码
 首当其冲的就是java历程,我之前预想的是如果是使用python备份,应该是python历程占用太多内存,没想到是java,我想了想极有可能是系统的 buffer/cache 导致内存过高,由于内存爆满发生在进行读写操作之后
验证

  1. [root@localhost home]# free -h
  2.               total        used        free      shared  buff/cache   available
  3. Mem:            39G        7.4G        295M        8.7M         31G         31G
  4. Swap:          3.0G         41M        3.0G
复制代码
buff/cache 竟然有31G 
先了解一下什么是buff/cache?

Buffer cache则主要是设计用来在系统对块装备进行读写的时候,对块进行数据缓存的系统来使用。比如我们在格式化文件系统的时候。
一样平常情况下两个缓存系统是一起配合使用的,比如当我们对一个文件进行写操作的时候,page cache的内容会被改变,而buffer cache则可以用来将page标志为不同的缓冲区,并纪录是哪一个缓冲区被修改了。这样,内核在后续实行脏数据的回写(writeback)时,就不用将整个page写回,而只需要写回修改的部门即可。
Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便开释出内存给急需内存的历程使用。
既然它主要用来做缓存,只是在内存够用的时候加速历程对文件的读写速度,那么在内存压力较大的情况下,当然有须要清空开释cache,作为free空间分给干系历程使用。以是一样平常情况下,我们认为buffer/cache空间可以被开释,这个明白是正确的。
但是这种清缓存的工作也并不是没有成本。以是陪同着cache清除的行为的,一样平常都是系统IO飙高。由于内核要对比cache中的数据和对应硬盘文件上的数据是否同等,如果不同等需要写回,之后才气回收。
尝试开释buffer/cache

sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延长的块 I/O 和读写映射文件。切记开释前最好sync一下,防止丢数据。
  1. sync && echo 1 > /proc/sys/vm/drop_caches
复制代码
实行之后发现内存已经正常,根本得出是 buffer/cache 中缓存的数据过多导致的内存爆满
实行之后需要将/proc/sys/vm/drop_caches 的值改成原来的0
  1. echo 0 > /proc/sys/vm/drop_caches
复制代码
但是我实行这个之后,产生了报错
  1. [root@localhost home]# echo 0 > /proc/sys/vm/drop_caches-bash: echo: write error: Invalid argument
复制代码
在研究这个报错之前我们先了解几个概念
   /proc/sys/vm/drop_caches

  清除缓存策略:
1:手动清除page cache
2:手动清除slab分配器中的对象(包括目次项和inode)
3:手动清除page cache和slab分配器中的对象
  0 是系统使用的,手动调整是不行的,而开释之后  /proc/sys/vm/drop_caches 显示为1
这个虽然是显示1,但是这个只是一种状态 echo 1 > /proc/sys/vm/drop_caches 是一次手动清除的行为,不会影响系统的主动清除内存

不过每次都要手动清除内存比较麻烦,我找到一个脚本
  1. #! /bin/bash# 需要开释内存的,内存使用百分比,可以传参,默认是85%max_rate=$1if [ ! "$max_rate" ] ; then        max_rate=85fiecho "max_rate: $max_rate"total=`free -m | awk 'NR==2' | awk '{print $2}'`used=`free -m | awk 'NR==2' | awk '{print $3}'`free=`free -m | awk 'NR==2' | awk '{print $4}'`rate=$(($used*100/$total));log=/usr/local/logs/mem.logecho "===========================" >> $logdate >> $logecho "current_rate: $rate"echo "Memory usage | [Total:${total}MB][Use:${used}MB][Free:${free}MB]" >> $logif [ "$rate" -ge "$max_rate" ] ; then        sync && echo 1 > /proc/sys/vm/drop_caches        sync && echo 2 > /proc/sys/vm/drop_caches        sync && echo 3 > /proc/sys/vm/drop_caches        echo "OK" >> $logelse        echo "Not required" >> $logfi
复制代码
但是这个脚本是根据总内存来判定的,我使用之后并不能起到效果,我改成了根据 buff/cache 和总内存的百分比来判定是否要进行清理
  1. #!/bin/bash# 需要开释内存的,缓存占用百分比,可以传参,默认是70%max_cache_rate=$1if [ ! "$max_cache_rate" ] ; then        max_cache_rate=70fiecho "max_cache_rate: $max_cache_rate"total_mem=$(free -m | awk 'NR==2{print $2}')cache_mem=$(free -m | awk 'NR==2{print $6}')cache_rate=$((cache_mem*100/total_mem))log=/usr/local/logs/mem.logecho "===========================" >> $logdate >> $logecho "current_cache_rate: $cache_rate%"echo "Memory usage | [Total:${total_mem}MB][Cache:${cache_mem}MB]" >> $logif [ "$cache_rate" -ge "$max_cache_rate" ] ; then        sync && echo 1 > /proc/sys/vm/drop_caches        sync && echo 2 > /proc/sys/vm/drop_caches        sync && echo 3 > /proc/sys/vm/drop_caches        echo "OK, cache memory released" >> $logelse        echo "Not required to release cache memory" >> $logfi
复制代码

每隔30分钟运行一次
  1. */30 * * * * /usr/bin/sh /home/mem.sh
复制代码
其他的办理方法
通过这个问题对这个buff/cache 有了了解,我就思索:
linux系统应该可以配置不使用buff/cache吧?
buff/cache 的系统主动回收,是不是也是可以配置主动回收的上限呢?
等等问题。我就找到了以下内容:
修改/etc/sysctl.conf 添加如下选项后就不会内存连续增加
  1. vm.dirty_ratio = 1
  2. vm.dirty_background_ratio=1
  3. vm.dirty_writeback_centisecs=2
  4. vm.dirty_expire_centisecs=3
  5. vm.drop_caches=3
  6. vm.swappiness =100
  7. vm.vfs_cache_pressure=163
  8. vm.overcommit_memory=2
  9. vm.lowmem_reserve_ratio=32 32 8
  10. kern.maxvnodes=3
复制代码

上面的设置比较粗暴,使cache的作用根本无法发挥。
先容一下详细的配置项:
dirty_ratio

这个参数控制文件系统的文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,表示当写缓冲使用到系统内存多少的时候,开始向磁盘写出数 据。增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当你需要连续、恒定的写入场合时,应该降低其数值,一样平常启动上缺省是 10。设1加速程序速度;
dirty_background_ratio

这个参数控制文件系统的pdflush历程,在何时革新磁盘。单位是百分比,表示系统内存的百分比,意思是当写缓冲使用到系统内存多少的时 候,pdflush开始向磁盘写出数据。增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当你需要连续、恒定的写入场合时, 应该降低其数值,一样平常启动上缺省是 5;
dirty_writeback_centisecs

这个参数控制内核的脏数据革新历程pdflush的运行隔断。单位是 1/100 秒。缺省数值是500,也就是 5 秒。如果你的系统是连续地写入动作,那么实际上照旧降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作;
dirty_expire_centisecs

这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,pdflush历程就开始思量写到磁盘中去。单位是 1/100秒。缺省是 30000,也就是 30 秒的数据就算旧了,将会革新磁盘。对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,由于缩小太多也会导致IO提高太快。发起设置为 1500,也就是15秒算旧。 
drop_caches

开释已经使用的cache;
page-cluster

该文件表示在写一次到swap区的时候写入的页面数量,0表示1页,1表示2页,2表示4页。
swapiness

该文件表示系统进行交换行为的程度,数值(0-100)越高,越可能发生磁盘交换。
vfs_cache_pressure

该文件表示内核回收用于directory和inode cache内存的倾向
  1. vm.dirty_ratio = 5    #dft 20  %
  2. vm.dirty_background_ratio =5 #dft 10 %
  3. vm.dirty_writeback_centisecs=100 #dft 500 is 5s
  4. vm.dirty_expire_centisecs=300    #dft 30000 is 30s
  5. vm.drop_caches=3  #dft  0
  6. vm.swappiness=100  #dft 60
  7. vm.vfs_cache_pressure=133  #dft 100
复制代码

目前我在使用的是脚本的方法,其他方法大家也可以试试 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表