今天第二次遇到Redis 「MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk」的問題。這個錯誤信息是Redis客戶端工具在保存數據時候拋出的異常信息。linux
網上查了一下,不少人都是建議「config set stop-writes-on-bgsave-error no」。這樣作實際上是很差的,這僅僅是讓程序忽略了這個異常,使得程序可以繼續往下運行,但實際上數據仍是會存儲到硬盤失敗!redis
上一次遇到這個問題是由於一個程序的Bug形成系統內存被耗盡了,後來修復了那個Bug問題就解決了。今天出現問題時查看系統內存還有2GB左右,「感受好像不是內存的緣故」(後面發現仍是由於內存的緣故)。工具
因爲Redis是daemon模式運行的,無法看到詳細的日誌。修改配置文件設置logfile參數爲文件(默認是stdout,建議之後安裝完畢就修改這個參數爲文件,否則會丟掉不少重要信息),重啓Redis,查看日誌,看到程序啓動時就有一行警告提示:this
「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' )使其生效。)spa
當時沒明白意思,就忽略了。再啓動Redis客戶端,程序保存數據時繼續報「MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk」異常,再查看Redis日誌,看到有這樣的錯誤提示「Can’t save in background: fork: Cannot allocate memory」,這個提示很明顯"Fork進程時內存不夠用了!"(仍是內存的問題)。日誌
經過谷歌查詢「Can’t save in background: fork: Cannot allocate memory」這個提示,找到了解決方法:xml
修改vm.overcommit_memory=1後問題果真解決了。htm
爲何系統明明還剩2GB的內存,Redis會說內存不夠呢?進程
網上查了一下,有人也遇到相似的問題,而且給出了很好的分析(詳見:http://www.linuxidc.com/Linux/2012-07/66079.htm),簡單地說:Redis在保存數據到硬盤時爲了不主進程假死,須要Fork一份主進程,而後在Fork進程內完成數據保存到硬盤的操做,若是主進程使用了4GB的內存,Fork子進程的時候須要額外的4GB,此時內存就不夠了,Fork失敗,進而數據保存硬盤也失敗了。內存