redis Can’t save in background: fork: Cannot allocate memory 解決方法

  • java日誌中報錯
redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
    at redis.clients.jedis.Protocol.processError(Protocol.java:66) ~[jedis-2.2.1.jar:na]
    at redis.clients.jedis.Protocol.process(Protocol.java:73) ~[jedis-2.2.1.jar:na]
    at redis.clients.jedis.Protocol.read(Protocol.java:138) ~[jedis-2.2.1.jar:na]
    at redis.clients.jedis.Connection.getIntegerReply(Connection.java:191) ~[jedis-2.2.1.jar:na]
    at redis.clients.jedis.Jedis.incr(Jedis.java:560) ~[jedis-2.2.1.jar:na]
  • redis日誌中報錯1:
Can't save in background: fork: Resource temporaily unavailable
  • redis日誌報錯2:
Can’t save in background: fork: Cannot allocate memory

原因是因爲,redis有個默認的選項:

stop-writes-on-bgsave-error yes

這個選項默認情況下,如果在RDB snapshots持久化過程中出現問題,設置該參數後,Redis是不允許用戶進行任何更新操作。

不徹底的解決方法是:將這個選項改爲false:

stop-writes-on-bgsave-error false

但是這樣只是當redis寫硬盤快照出錯時,可以讓用戶繼續做更新操作,但是寫硬盤仍然是失敗的;

徹底的解決方法:

  • 編輯文件/etc/sysctl.conf,添加:
vm.overcommit_memory=1

然後執行下列命令,使其生效:

sysctl -p

vm.overcommit_memory 這個參數又是幹什麼的呢?
Linux對大部分申請內存的請求都回復"yes",以便能跑更多更大的程序。因爲申請內存後,並不會馬上使用內存,將這些不會使用的空閒內存分配給其它程序使用,以提高內存利用率,這種技術叫做Overcommit。一般情況下,當所有程序都不會用到自己申請的所有內存時,系統不會出問題,但是如果程序隨着運行,需要的內存越來越大,在自己申請的大小範圍內,不斷佔用更多內存,直到超出物理內存,當linux發現內存不足時,會發生OOM killer(OOM=out-of-memory)。它會選擇殺死一些進程(用戶態進程,不是內核線程,哪些佔用內存越多,運行時間越短的進程越有可能被殺掉),以便釋放內存。

參考博文:https://blog.csdn.net/zqz_zqz/article/details/53384854

如果還不能解決,那麼進行以下步驟:
在安裝redis的服務器上,使用命令登錄redis:

redis-cli

然後輸入配置的用戶名和密碼(我的是:auth/123456)
查看redis內存佔用情況:

info
# Memory
# 數據佔用了多少內存(字節 byte)
used_memory:13490096 
# 數據佔用了多少內存(帶單位的,可讀性好)
used_memory_human:12.87M 
# redis佔用了多少內存
used_memory_rss:13490096
# 佔用內存的峯值(字節)  
used_memory_peak:15301192 
# 佔用內存的峯值(帶單位的,可讀性好)
used_memory_peak_human:14.59M 
# lua引擎所佔用的內存大小(字節)
used_memory_lua:31744  
# 內存碎片率
mem_fragmentation_ratio:1.00
# redis內存分配器版本,在編譯時指定的。有libc、jemalloc、tcmalloc這3種。
mem_allocator:libc 

看 used_memory就行了;

根據內存佔用情況,編輯redis配置文件(我的是/etc/redis.conf),修改文件中對應的最大內存大小(537行)和策略(560行)以小編的爲例:

# 537行修改後爲:
maxmemory 6GB

# 560行修改後爲:
maxmemory-policy allkeys-lru

然後重啓redis即可:

service redis restart

redis佔用內存滿了的解決方法

1. 增加內存

2. 採用內存淘汰策略

  • redis內存淘汰策略:當redis內存達到最大的內存限制會申請額外的內存空間。對於怎麼處理需要新寫入且需要申請額外空間的數據?這時候就需要採用內存淘汰策略了。

    • noeviction(默認策略):當內存不足以容納新寫入數據時,新寫入操作會報錯。
    • allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。
    • allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。
    • volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。
    • volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。
    • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除。
  • 推薦兩種算法方案:

    • LRU(最近最少使用淘汰算法(Least Recently Used))
      LRU是淘汰最長時間沒有被使用的數據。其核心思想就是“如果數據最近被訪問過,那麼將來被訪問的機率也更高”。基本思路:如果最近使用得比較多的數據就把他放到列表頭部,依次更新,從列表尾部的依次淘汰,就是刪除對應的key。
    • LFU(最不經常使用淘汰算法(Least Frequently Used))
      LFU是淘汰一段時間內,使用次數最少的數據。它是基於“如果一個數據在最近一段時間內使用次數很少,那麼在將來一段時間內被使用的可能性也很小”的思路。
      在這裏插入圖片描述

3. 使用redis集羣

參考博客:https://blog.csdn.net/weixin_44655002/article/details/97489990

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章