Redis 寫磁碟出錯 Cannot allocate memory

蔣建勇發表於2018-07-30

故障簡介

早上檢視Redis日誌的時候發現Redis一直在報錯

[1524] 24 Mar 10:00:56.037 * 1 changes in 900 seconds. Saving...
[1524] 24 Mar 10:00:56.037 # Can`t save in background: fork: Cannot allocate memory

Redis資料回寫機制

資料回寫分同步和非同步兩種方式

  • 同步回寫(SAVE), 主程式直接向磁碟迴寫資料. 在資料量大的情況下會導致系統假死很長時間
  • 非同步回寫(BGSAVE), 主程式fork後, 複製自身並通過這個新的程式回寫磁碟, 回寫結束後新程式自行關閉.

由於 BGSAVE 不需要主程式阻塞, 系統也不會假死, 一般會採用 BGSAVE 來實現資料回寫.

故障分析

在小記憶體的程式上做fork, 不需要太多資源. 但當這個程式的記憶體空間以G為單位時, fork就成為一件很恐怖的操作.
在16G記憶體的足跡上fork 14G的程式, 系統肯定 Cannot allocate memory.
主機的Redis 改動的越頻繁 fork程式也越頻繁, 所以一直在 Cannot allocate memory

解決方案

直接修改核心引數 vm.overcommit_memory = 1, Linux核心會根據引數 vm.overcommit_memory 引數的設定決定是否放行。

vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:則比較 此次請求分配的虛擬記憶體大小和系統當前空閒的實體記憶體加上swap,決定是否放行。
vm.overcommit_memory =2:則會比較程式所有已分配的虛擬記憶體加上此次請求分配的虛擬記憶體和系統當前的空閒實體記憶體加上swap,決定是否放行。

/**
 * 在/etc/sysctl.conf檔案裡面加入或者直接刪除也可以,因為它預設值就是 
 */
sudo echo `vm.overcommit_memory = 1` >> /etc/sysctl.conf
sudo sysctl -p

相關文章