发现在redis的日志中出现如Can't save in background : fork: cannot allocate memory
错误,如图:
不难看出这是redis在尝试用子进程进行数据备份时无法从系统中分配到内存的提示(假设fork后父子进程进行了内存数据的复制,当然有copy on write技术的加入实际所需要内存会小),这是由于Linux系统的对程序申请内存时有相关策略控制引起的
redis官方建议的解决方案是把vm.overcommit_memory设置为1
出现这种情况一般满足以下三点:
- 系统中所有程序已经申请的内存+加上准备要申请的内存大小接近了系统预设阈值,即Committed_AS接近CommittedLIMIT (memory of all processes is close to or more than half of allocated memory/system memory(memory is 32+GB and 27 GB is left))
- 系统配置vm.overcommit_memory的值为0(vm.overcommit_memory is set to 0)
- 此时redis正在进行后台数据备份(when redis does a background save.)
linux系统预设的阈值可通过grep -i commit /proc/meminfo
查看,其中:
Committed_AS: 表示所有进程已经申请的内存总大小
CommittedLIMIT: 所有进程总共可以申请内存+swap的上限值
CommittedLIMIT的计算公式为: (Physical RAM * vm.overcommit_ratio / 100) + Swap
vm.overcommit_ratio默认为50%
关于linux系统对程序进行内存申请的策略控制由vm.overcommit_memory
设置,有三种:
- 0: Heuristic overcommit handling. 这是默认值,它允许 overcommit,内核利用某种算法计算你的内存申请是否合理,它认为不合理就会拒绝 overcommit
- 1: Always overcommit. 允许 overcommit,对内存申请来者不拒
- 2: Don’t overcommit. 禁止 overcommit, 如果要设置为该策略,配合overcommit_ratio一起设置
to set the overcommit_memory parameter to 1 temporarily, run the following command:
echo 1 > /proc/sys/vm/overcommit_memory
To set this value persistently, add
vm.overcommit_memory=1
in /etc/sysctl.conf
then run the following command:
sysctl -p
参考链接:
https://jingchao.org.cn/2020/03/25/Linux%E4%B8%AD%E7%9A%84Committed_AS%E4%B8%8ECommitLimit.html
https://www.kernel.org/doc/Documentation/vm/overcommit-accounting