2012-08-01 80 views
27

所有: 这里是Redis的bgsave失败,因为叉无法分配内存

   total  used  free  shared buffers  cached 
Mem:   64433  49259  15174   0   3   31 
-/+ buffers/cache:  49224  15209 
Swap:   8197  184  8012 

我Redis的服务器使用了46G内存“免费-m”我的服务器内存的信息,几乎15G的记忆中留下自由

据我所知,fork是copy的写入,当有15G空闲内存时,应该不会失败,这对malloc必要的内核结构来说已经足够了。

此外,当redis服务器使用42G内存时,bgsave可以,叉也可以。

是否有任何vm参数可以调整以使fork返回成功?

谢谢。

+0

Get'double '更多的记忆 – surfer190 2017-05-19 11:34:11

回答

14

从PROC(5):

/proc/sys/vm/overcommit_memory 
       This file contains the kernel virtual memory accounting mode. Values are: 
       0: heuristic overcommit (this is the default) 
       1: always overcommit, never check 
       2: always check, never overcommit 
       In mode 0, calls of mmap(2) with MAP_NORESERVE set are not checked, and the default check is very weak, leading to the risk of getting a process "OOM-killed". Under Linux 2.4 
       any non-zero value implies mode 1. In mode 2 (available since Linux 2.6), the total virtual address space on the system is limited to (SS + RAM*(r/100)), where SS is the size 
       of the swap space, and RAM is the size of the physical memory, and r is the contents of the file /proc/sys/vm/overcommit_ratio. 
46

更具体地,从Redis FAQ

Redis的背景节省模式依赖于写入时复制语义在现代操作系统叉:Redis的叉子(创建一个子进程),它是父进程的精确副本。子进程将磁盘上的数据库转储并最终退出。从理论上讲,孩子应该尽可能多地使用父母作为副本的内存,但实际上要感谢大多数现代操作系统实现的写入时复制语义,父进程和子进程将共享公用内存页面。只有当它在孩子或父母中发生变化时,页面才会被复制。由于理论上所有的页面可能会在孩子进程保存时发生变化,因此Linux无法预先知道孩子需要多少内存,所以如果overcommit_memory设置为零,那么分支将失败,除非有足够的空闲RAM需要真正复制所有父内存页面,结果是如果您拥有3 GB的Redis数据集并且只有2 GB的空闲内存,则会失败。

将overcommit_memory设置为1表示Linux放宽并以更乐观的分配方式执行分叉,而这确实是Redis需要的。作为OS认为它写入到磁盘

的Redis并不需要尽可能多的内存,这样可以先发制人失败叉。

29

修改/etc/sysctl.conf,加上

vm.overcommit_memory=1 

然后通过

在FreeBSD重启的sysctl: $ sudo的/etc/rc.d/sysctl重装

在Linux: $ sudo sysctl -p /etc/sysctl.conf

相关问题