记一次内存占用过高的分析

客户给我反应,他们的PostgreSQL服务器的内存占用率高达99%,只有一点内存可以分配了,让我帮忙看看。

 

没有问题,虽然剩余内存很少了,只有500M左右,但是其中cache的内存很多,应用可分配的内存依然有50G,不用担心。

 

 

1、首先看看/proc/meminfo内容:

xxxx:~ # cat /proc/meminfo 

MemTotal:       65786904 kB    所有可用RAM大小 (即物理内存减去一些预留位和内核的二进制代码大小)
MemFree:          515316 kB    LowFree与HighFree的总和,被系统留着未使用的内存  这里503M左右
MemAvailable:   47765096 kB   应用可分配内存 echo "47765096/1024/1024"|bc = 45G
Buffers:            2180 kB   buffer cache,块缓存(buffer cache),则是内核为了加速对底层存储介质的访问速度,而构建的一层缓存。他缓存部分磁盘数据,当有磁盘读取请求时,会首先查看块缓存中是否有对应的数据,如果有的话,则直接将对应数据返回,从而减少对磁盘的访问。
Cached:         46499916 kB   page cache,缓存文件内容,dirty_ratio提到的脏页就是指page cache(等于 diskcache minus SwapCache )
SwapCached:          456 kB   交换空间的大小,已经被交换出来的内存,但仍然被存放在swapfile中。用来在需 要的时候很快的被替换而不需要再次打开I/O端口。
Active:         35838856 kB   在活跃使用中的缓冲页面文件的大小,除非非常必要否则不会被移作他用.
Inactive:       22011252 kB   在不经常使用中的缓冲页面文件的大小,可能被用于其他途径.
CommitLimit:   7952968 kB   CommitLimit为当前系统可以申请的总内存
Committed_AS: 8895092 kB   当前已经申请的内存,记住是申请

 

MemAvailable的解释:

MemAvailable = MemFree+Active(file)+Inactive(file)-(watermark+min(watermark,Active(file)+Inactive(file)/2)) 

file占用的内存是可以释放的,但是释放的过多,会导致swap发生,减去部分内存的目的是避免swap 

检查/proc/meminfo文件,通过将“MemFree + Buffers+ Cached”相加,预估有多少可用内存,这在十年前是可以,但是在今天肯定是不对的。
因为缓存包含存不能释放的page cache,例如shared memory segments、tmpfs、ramfs,它不包括可收回的slab内存,比如在大多数空闲的系统中,存在很多文件时,它会占用大量的系统内存。在系统没有发生交换时,预估需要多少available内存才可以启动新的应用程序。这个available字段不同于cache或free字段所提供的数据,它除了要考虑到page cache,还要考虑到当项目在使用时,并不是所有的slabs都能被回收这一情况。

 

 2、再看看free:xxxx:~ # free

             total           used               free       shared      buffers    cached
Mem:      65786904     65271240            515664     4846584       2180   52825696
-/+ buffers/cache:     12443364              53343540
Swap:     16779260      5324                16773936
 

第1行 Mem: total:表示物理内存总量。
used:表示总计分配的内存,但其中可能部分缓存并未实际使用(包含buffers 与cache )。
free:未被分配的内存。
shared:共享内存,PG数据库经常使用,也包含在used中。
buffers:buffer cache,可被征用。
cached:文件系统缓存page cache,可被征用。buffer 与cache 的区别见后面。

 

说明:
total = used + free 
-/+ buffers/cached: 
-:真实使用的内存:used - buffers-cached 或total - free - buffers -cached
+:可被挪用的内存:free + buffers + cached

 


3、Page Cache和Buffer Cache的关系:

Page Cache
Page Cache以Page为单位,缓存文件内容。缓存在Page Cache中的文件数据,能够更快的被用户读取。同时对于带buffer的写入操作,数据在写入到Page Cache中即可立即返回,而不需等待数据被实际持久化到磁盘,进而提高了上层应用读写文件的整体性能。

Buffer Cache
磁盘的最小数据单位为sector,每次读写磁盘都是以sector为单位对磁盘进行操作。sector大小跟具体的磁盘类型有关,有的为512Byte, 有的为4K Bytes。无论用户是希望读取1个byte,还是10个byte,最终访问磁盘时,都必须以sector为单位读取,如果裸读磁盘,那意味着数据读取的效率会非常低。同样,如果用户希望向磁盘某个位置写入(更新)1个byte的数据,他也必须整个刷新一个sector,言下之意,则是在写入这1个byte之前,我们需要先将该1byte所在的磁盘sector数据全部读出来,在内存中,修改对应的这1个byte数据,然后再将整个修改后的sector数据,一口气写入磁盘。为了降低这类低效访问,尽可能的提升磁盘访问性能,内核会在磁盘sector上构建一层缓存,他以sector的整数倍力度单位(block),缓存部分sector数据在内存中,当有数据读取请求时,他能够直接从内存中将对应数据读出。当有数据写入时,他可以直接再内存中直接更新指定部分的数据,然后再通过异步方式,把更新后的数据写回到对应磁盘的sector中。这层缓存则是块缓存Buffer Cache。

 

在我们进行数据持久化,对文件内容进行落盘处理时,我们时常会使用fsync操作,该操作会将文件关联的脏页(dirty page)数据(实际文件内容及元数据信息)一同写回磁盘。这里提到的脏页(dirty page)即为页缓存(page cache)。

块缓存(buffer cache),则是内核为了加速对底层存储介质的访问速度,而构建的一层缓存。他缓存部分磁盘数据,当有磁盘读取请求时,会首先查看块缓存中是否有对应的数据,如果有的话,则直接将对应数据返回,从而减少对磁盘的访问。

 

4、回到问题,再看看top:

xxxx:~ # top 

top - 14:31:15 up 31 days, 20:12,  3 users,  load average: 0.43, 0.42, 0.38
Tasks: 927 total,   1 running, 925 sleeping,   0 stopped,   1 zombie
%Cpu(s):  1.5 us,  1.1 sy,  0.0 ni, 97.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  65786904 total, 65275224 used,   511680 free,     2180 buffers
KiB Swap: 16779260 total,     5324 used, 16773936 free. 52825968 cached Mem

  

从top中也可以看到大概,虽然free很少,但是cached Mem很大,swap很少,从侧面反应内存还是够的,所以,free和top的结果比较一致,memento中的则有一点差距,

 

所以,更加靠谱的是MEMAvailable,客户的内存完全不用担心,Linux的内存有个特点,只要内存够,就不会将部分内存交换出来,这样来提高系统性能。就算内存满了,也会优先往swap中交换。当然数据库应用应当尽量减少内存的交换,尤其是频繁的swap交换时,应当考虑优化服务器或者数据库参数,提高系统性能。

 

posted @ 2018-12-11 15:23  狂神314  阅读(2560)  评论(0)    收藏  举报