运行redis报错MISCONF Redis is configured to save RDB snapshots
laoyan 2019-02-15 15:45:57
分 享


问题现象


运行系统频繁出现有关redis的报错:“MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk


问题原因


这个错误信息是Redis客户端工具在保存数据时候抛出的异常信息,由于Redis是daemon模式运行的,没法看到详细的日志。修改配置文件设置logfile参数为文件(默认是stdout,建议以后安装完毕就修改这个参数为文件,不然会丢掉很多重要信息),重启Redis,查看日志,看到程序启动时就有一行警告提示:


“WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.
 To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run 
 the command 'sysctl vm.overcommit_memory=1' for this to take effect.”


(警告:过量使用内存设置为0!在低内存环境下,后台保存可能失败。为了修正这个问题,请在/etc/sysctl.conf 添加一项 'vm.overcommit_memory = 1' ,然后重启(或者运行命令'sysctl vm.overcommit_memory=1' )使其生效。)


解决方法


方法一:忽略这个报错,但是实际上redis还是写入数据到磁盘错误,此方法不推荐


redis-cli
config set stop-writes-on-bgsave-error no


方法二:推荐此方法


在/etc/sysctl.conf 添加一项 


vm.overcommit_memory = 1


然后重启


问题解释


Redis的数据回写机制分同步和异步两种:


(1)同步回写即SAVE命令,主进程直接向磁盘回写数据。在数据大的情况下会导致系统假死很长时间,所以一般不是推荐的。

(2)异步回写即BGSAVE命令,主进程fork后,复制自身并通过这个新的进程回写磁盘,回写结束后新进程自行关闭。由于这样做不需要主进程阻塞,系统不会假死,一般默认会采用这个方法。


在小内存的进程上做一个fork,不需要太多资源,但当这个进程的内存空间以G为单位时,fork就成为一件很恐怖的操作。何况在8G内存的主机上fork 4G内存的进程呢?肯定会报内存无法分配的,Linux内核会根据参数vm.overcommit_memory参数的设置决定是否放行。


vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:则比较 此次请求分配的虚拟内存大小和系统当前空闲的物理内存加上swap,决定是否放行。
vm.overcommit_memory = 2:则会比较 进程所有已分配的虚拟内存加上此次请求分配的虚拟内存和系统当前的空闲物理内存加上swap,决定是否放行。


问题总结


出现这个问题一般是由于系统内存不足问题(检查服务器内存明明还有剩余,但还是会报错),为什么系统明明还剩2GB的内存,Redis会说内存不够?

简单地说:Redis在保存数据到硬盘时为了避免主进程假死,需要Fork一份主进程,然后在Fork进程内完成数据保存到硬盘的操作,如果主进程使用了4GB的内存,Fork子进程的时候需要额外的4GB,此时内存就不够了,Fork失败,进而数据保存硬盘也失败了。


我要小额支持下

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

取消
吐槽一下

游客

所有吐槽
  • 暂时还没有吐槽,赶紧来吐槽!