Redis做系統緩存,歷史原因緩存策略和緩存內容不太適應增長的業務量,死皮賴臉扛着dba各種dissN個日日夜夜后決定清理一波僵屍。
但將無用的key刪除后,並沒有真正的釋放內存,查看Redis的相關文檔,也沒有釋放內存的相關命令。看着儀表盤的百分比甚是撓頭。。。
查了些資料了解了下,改日再請教請教dba大大們。。。
官方已經說了具體原因
https://redis.io/topics/memory-optimization
概括了點內容:
這不是Redis本身的問題,Redis本身確實已經調用free釋放這些內存。這應該是使用的底層C運行時的問題。
當鍵被刪除時,Redis並不總是釋放(返回)內存到操作系統。這並不是Redis的特別之處,但大多數malloc()實現都是這樣工作的。
例如一個實例有5gb的數據,然后刪除相當於2gb的數據,used_memory_rss可能仍會5 gb左右。這是因為底層分配器不能輕松地釋放內存。例如,通常將刪除的大多數鍵分配到與其他仍然存在的鍵相同的頁面中。
然而分配器是聰明和能夠重用空閑塊的內存,所以在你釋放2 gb的5 gb的數據集,當你開始再次增加鍵,您將看到used_memory_rss保持穩定而不會再增加很多。分配器基本上是嘗試重用以前(邏輯上)釋放的2GB內存。
就glibc來說,在分配大於128k的內存時使用mmap,而使用brk/sbrk在heap中分配小內存。通過mmap申請的內存在調用free后能馬上返還給系統,而heap中的內存就不一定,除非釋放的內存是heap中連續的大塊。
Redis本身沒有內存管理機制,只有一個使用量的統計功能 。每次需要創建對象,都是直接調用malloc申請,而Redis中的對象基本都比較小,所以基本都是在heap中的內存。
解決方案
通過原因可以知道,我們其實不用去關注。
特別是我們定義了maxmemory后,並且定義了maxmemory_policy,那么即使內存滿了,redis也會按照淘汰機制方案,清除一些不需要的key,來存放新的key。
但是如果已經影響到系統內存使用了,也有下面三種方案:
- 可以通過 MEMORY PURGE命令進行內存整理。(瞬時,能稍微騰出rss內存空間)
- 開啟activedefrag,熱碎片整理。(會占用CPU,在主線程執行,可以設置CPU占用率)
- 重啟。
看了解決方案,然后還是去請教dba大大吧。。。。
