轉載自:http://www.redicecn.com/html/Linux/20131125/468.html Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk"問題的解決
今天第二次遇到Redis “MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk”的問題。這個錯誤資訊是Redis用戶端工具在儲存資料時候拋出的異常資訊。
網上查了一下,很多人都是建議“config set stop-writes-on-bgsave-error no”。這樣做其實是不好的,這僅僅是讓程式忽略了這個異常,使得程式能夠繼續往下運行,但實際上資料還是會儲存到硬碟失敗。
上一次遇到這個問題是因為一個程式的Bug造成系統記憶體被耗盡了,後來修複了那個Bug問題就解決了。今天出現問題時查看系統記憶體還有2GB左右,“感覺好像不是記憶體的緣故”(後面發現還是因為記憶體的緣故)。
由於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用戶端,程式儲存資料時繼續報“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進程時記憶體不夠用了。"(還是記憶體的問題)。
通過Google查詢“Can’t save in background: fork: Cannot allocate memory”這個提示,找到瞭解決方法: view plain copy to clipboard print ? // 原文:http://pydelion.com/2013/05/27/redis-cant-save-in-background-fork-cannot-allocate-memory/ If you get this error Can't save in background: fork: Cannot allocate memory it means that your current database is bigger than memory you have. To fix the issue enable vm.overcommit_memory: sysctl vm.overcommit_memory=1 To have if after reboot add this line to /etc/sysctl.cnf: vm.overcommit_memory=1
修改vm.overcommit_memory=1後問題果然解決了。
為什麼系統明明還剩2GB的記憶體,Redis會說記憶體不夠呢。
網上查了一下,有人也遇到類似的問題,並且給出了很好的分析(詳見:http://www.linuxidc.com/Linux/2012-07/66079.htm),簡單地說:Redis在儲存資料到硬碟時為了避免主進程假死,需要Fork一份主進程,然後在Fork進程內完成資料儲存到硬碟的操作,如果主進程使用了4GB的記憶體,Fork子進程的時候需要額外的4GB,此時記憶體就不夠了,Fork失敗,進而資料儲存硬碟也失敗了。