上一篇文章,我已經嘗試過,用設定的方式,去限制redis記憶體的佔用大小,結果發現是不可行的。(redis不會區分冷熱資料,保留冷資料在硬碟上)。那麼如果要正常運行redis,就需要知道,redis最多可以佔用多少記憶體,保留多少記憶體。
結論:
極限情況:留出一倍記憶體。比如你的redis資料佔用了8G記憶體,那麼你還需要再預留8G空閑記憶體。也就是記憶體需求是16G。記憶體佔用率低於50%是最安全的。
普通情況:正常情況下,在序列化周期內,不會更改所有資料,只會有部分資料更改,那麼,預留出可能產生的更改部分的空間,就行。如果實在要說一個資料的話,記憶體佔用率低於75%都是安全的。
比如我們這個遊戲伺服器的,N台資料服務器之一的截圖:
如上圖,16G的記憶體,已經使用了64%了。但是實際上,在fork序列化的時候,只多佔用了200多M的記憶體而已。因為只變動了200多M。 也就是說,使用記憶體使用量率即便達到80%,也是安全的。因為Copy-On-Write就需要200M而已。
以下是擴充閱讀,原文連結: https://searchdatabase.techtarget.com.cn/7-21572/
多留一倍記憶體是最安全的。
重寫AOF檔案和RDB檔案的進程(即使不做持久化,複製到Slave的時候也要寫RDB)會fork出一條新進程來, 採用了作業系統的Copy-On-Write策略(如果父進程的記憶體沒被修改,子進程與父進程共用Page。如果父進程的Page被修改, 會複製一份改動前的內容給新進程),留意Console打出來的報告,如”RDB: 1215 MB of memory used by copy-on-write”。
在系統極度繁忙時,如果父進程的所有Page在子進程寫RDB過程中都被修改過了,就需要兩倍記憶體。
按照Redis啟動時的提醒,設定 vm.overcommit_memory = 1 ,使得fork()一條10G的進程時,因為COW策略而不一定需要有10G的free memory.
當最大記憶體到達時,按照配置的Policy進行處理, 預設policy為volatile-lru, 對設定了expire time的key進行LRU清除(不是按實際expire time)。如果沒有資料設定了expire time或者policy為noeviction,則直接報錯,但此時系統仍支援get之類的讀操作。 另外還有幾種policy,比如volatile-ttl按最接近expire time的,allkeys-lru對所有key都做LRU。
原來2.0版的VM(將Value放到磁碟,Key仍然放在記憶體),2.4版後又不支援了。(ps. 這是個坑。我以前記得有這麼個東西)