【问题标题】:redis bgsave failed because fork Cannot allocate memoryredis bgsave 失败,因为 fork 无法分配内存
【发布时间】:2012-07-29 22:53:02
【问题描述】:

全部: 这是我的服务器内存信息,带有“free -m”

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

我的 redis-server 已经使用了 46G 内存,还有将近 15G 内存可用

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

另外,当redis-server使用42G内存时,bgsave可以,fork也可以。

我可以调整任何 vm 参数以使 fork 返回成功吗?

【问题讨论】:

  • 获取double更多内存

标签: linux-kernel redis fork


【解决方案1】:

来自 proc(5) 手册页:

/proc/sys/vm/overcommit_memory

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

0:启发式过度使用(这是默认设置)

1:总是过度使用,从不检查

2:始终检查,从不过度使用

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

【讨论】:

    【解决方案2】:

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

    vm.overcommit_memory=1
    

    然后重启 sysctl:

    在 FreeBSD 上:

    sudo /etc/rc.d/sysctl reload
    

    在 Linux 上:

    sudo sysctl -p /etc/sysctl.conf
    

    【讨论】:

    • 除了重新加载之外,您还可以(至少在 debian 中):sysctl -w vm.overcommit_memory=1,然后在备份完成后返回 sysctl -w vm.overcommit_memory=0
    【解决方案3】:

    更具体地说,来自Redis FAQ

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

    将 overcommit_memory 设置为 1 表示 Linux 放松并以更乐观的分配方式执行分叉,而这确实是你想要的 Redis。

    Redis 不需要操作系统认为它写入磁盘所需的那么多内存,因此可能会先发制人地使 fork 失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-21
      • 2015-04-27
      • 2017-09-24
      • 2013-08-24
      • 2013-03-14
      • 2015-09-22
      • 2015-08-17
      • 1970-01-01
      相关资源
      最近更新 更多