redis bgsave失败,因为fork无法分配内存



全部:这是我的服务器内存信息与"免费-m"

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

我的redis服务器使用了46G内存,几乎还有15G内存可用

据我所知,fork是写时复制,当有15G的可用内存时,它应该不会失败,这足以对必要的内核结构进行malloc。

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

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

更具体地说,来自Redis常见问题

Redis后台保存模式依赖于现代操作系统中fork的写时复制语义:Redis forks(创建一个子进程)是父进程的精确副本。子进程将DB转储到磁盘上并最终退出。理论上,子进程应该使用与作为副本的父进程一样多的内存,但实际上,由于大多数现代操作系统实现了写时复制语义,父进程和子进程将共享公共内存页。只有当页面在子级或父级中发生更改时,才会复制该页面。由于理论上所有页面都可能在子进程保存时发生变化,Linux无法提前告知子进程将占用多少内存,因此如果overcommit_memory设置设置为零,则fork将失败,除非有足够多的可用RAM来真正复制所有父内存页面,结果是,如果你有一个3 GB的Redis数据集,只有2 GB的可用内存,它就会失败。

将overcommit_memory设置为1意味着Linux可以放松并以更乐观的分配方式执行fork,这确实是Redis想要的。

Redis不需要像操作系统认为的那样多的内存来写入磁盘,因此可能会预先使fork失败。

修改/etc/sysctl.conf并添加:

vm.overcommit_memory=1

然后用重新启动sysctl

在FreeBSD:上

sudo /etc/rc.d/sysctl reload

在Linux上:

sudo sysctl -p /etc/sysctl.conf

来自proc(5)手册页:

/proc/sys/vm/overcommit_memory

此文件包含内核虚拟内存记帐模式。值为:

0:启发式过度承诺(这是默认值)

1:总是过度承诺,从不检查

2:始终检查,切勿过度使用

在模式0中,不检查设置了MAP_NORESERVE的mmap(2)的调用,并且默认检查非常弱,导致进程"OOM被终止"的风险。在Linux 2.4下任何非零值都意味着模式1。在模式2中(自Linux 2.6起可用),系统上的总虚拟地址空间限制为(SS+RAM*(r/100)),其中SS是大小交换空间的大小,RAM是物理内存的大小,r是文件/proc/sys/vm/overcommit_tratio的内容。

Redis基于fork的快照方法可以有效地将物理内存使用量增加一倍,并在类似您的情况下轻松OOM。依赖linux虚拟内存来执行快照是有问题的,因为linux对Redis数据结构没有可见性。

最近发布了一个新的redis兼容项目Dragonfly。除其他外,它完全解决了OOM问题。(披露-我是这个项目的作者)。

最新更新