最近查看了一下redis運行情況,發現公司測試服務器的redis內存不太夠用,可是實際佔用內存的數據量其實不大,之前也沒有這種狀況,以前在cache層新增了一個防刷積分任務的邏輯纔會這樣,搜索一下緣由,發現原來是產生了大量的內存碎片。redis
首先,查看redis的內存狀態,要用info memory指令緩存
ps:(這個是我flushdb後的結果,反面教材來的。。。) 圖中幾個參數的意義:服務器
一、used_memory:ide
已經使用了的內存大小,包括redis進程內部開銷和你的cache的數據所佔用的內存,單位byte。性能
二、used_memory_human:測試
用戶數據所佔用的內存,就是你緩存的數據的大小。lua
三、used_memory_rss:(rss for Resident Set Size)blog
表示redis物理內存的大小,即向OS申請了多少內存使用與used_memory的區別在後面解釋。進程
四、used_memory_peak:圖片
redis內存使用的峯值。
五、used_memory_peak_human:
用戶cache數據的峯值大小。
六、used_memory_lua:
執行lua腳本所佔用的內存。
七、mem_fragmentation_ratio:
內存碎片率,計算公式: ratio指數>1代表有內存碎片,越大代表越多,<1代表正在使用虛擬內存,虛擬內存其實就是硬盤,性能比內存低得多,這是應該加強機器的內存以提升性能。通常來講,mem_fragmentation_ratio的數值在1 ~ 1.5之間是比較健康的。
八、mem_allocator:
在編譯時指定的Redis使用的內存分配器,能夠是libc、jemalloc、tcmalloc,默認是jemalloc。jemalloc在64位系統中,將內存空間劃分爲小、大、巨大三個範圍;每一個範圍內又劃分了許多小的內存塊單位;存儲數據的時候,會選擇大小最合適的內存塊進行存儲。 jemalloc劃分的內存單元以下圖所示: (圖侵刪)
產生緣由
能夠這樣認爲,redis產生內存碎片有兩個緣由, A:redis自身的內存分配器。 B:修改cache的值,且修改後的value與原來value的大小差別較大。
進程須要用內存的話,會先經過OS向device申請,而後纔可以使用。通常進程在不須要使用的時候,會釋放掉這部份內存並返回給device。可是redis做者可能爲了更高的性能,因此在redis中實現了本身的內存分配器來管理內存,不會立刻返還內存,不用每次都向OS申請了,從而實現高性能。
可是,在內存分配器的那張圖片咱們知道,redis的每一個k-v對初始化的內存大小是最適合的,當這個value改變的而且原來內存大小不適用的時候,就須要從新分配內存了。(可是value存比原來小不知道會不會產生碎片)。從新分配以後,就會有一部份內存redis沒法正常回收,一直佔用着。
知道了緣由就能夠解決問題了,網上找到了兩個解決方案: 一、重啓redis服務,簡單粗暴。 二、redis4.0以上可使用新增指令來手動回收內存碎片,配置監控使用性能更佳,具體你們能夠本身去查。