redis調優 -- 內存碎片


 

 

最近查看了一下redis運行狀況,發現公司測試服務器的redis內存不太夠用,但是實際占用內存的數據量其實不大,以前也沒有這種情況,之前在cache層新增了一個防刷積分任務的邏輯才會這樣,搜索一下原因,發現原來是產生了大量的內存碎片。

首先,查看redis的內存狀態,要用info memory指令


 
2018-06-01_110028.png

ps:(這個是我flushdb后的結果,反面教材來的。。。)
圖中幾個參數的意義:

1、used_memory:

已經使用了的內存大小,包括redis進程內部開銷和你的cache的數據所占用的內存,單位byte。

2、used_memory_human:

用戶數據所占用的內存,就是你緩存的數據的大小。

3、used_memory_rss:(rss for Resident Set Size)

表示redis物理內存的大小,即向OS申請了多少內存使用與used_memory的區別在后面解釋。

4、used_memory_peak:

redis內存使用的峰值。

5、used_memory_peak_human:

用戶cache數據的峰值大小。

6、used_memory_lua:

執行lua腳本所占用的內存。

7、mem_fragmentation_ratio:

 

 

內存碎片率,計算公式:
 
190138549569988.png

ratio指數>1表明有內存碎片,越大表明越多,<1表明正在使用虛擬內存,虛擬內存其實就是硬盤,性能比內存低得多,這是應該增強機器的內存以提高性能。一般來說,mem_fragmentation_ratio的數值在1 ~ 1.5之間是比較健康的。

8、mem_allocator:

在編譯時指定的Redis使用的內存分配器,可以是libc、jemalloc、tcmalloc,默認是jemalloc。jemalloc在64位系統中,將內存空間划分為小、大、巨大三個范圍;每個范圍內又划分了許多小的內存塊單位;存儲數據的時候,會選擇大小最合適的內存塊進行存儲。
jemalloc划分的內存單元如下圖所示:


 
1174710-20180327001126509-2023165562.png

(圖侵刪)

----------------------------------------------------- 分割線 ------------------------------------------------

產生原因

可以這樣認為,redis產生內存碎片有兩個原因,
A:redis自身的內存分配器。
B:修改cache的值,且修改后的value與原來value的大小差異較大。

進程需要用內存的話,會先通過OS向device申請,然后才能夠使用。一般進程在不需要使用的時候,會釋放掉這部分內存並返回給device。但是redis作者可能為了更高的性能,所以在redis中實現了自己的內存分配器來管理內存,不會馬上返還內存,不用每次都向OS申請了,從而實現高性能。

但是,在內存分配器的那張圖片我們知道,redis的每個k-v對初始化的內存大小是最適合的,當這個value改變的並且原來內存大小不適用的時候,就需要重新分配內存了。(但是value存比原來小不知道會不會產生碎片)。重新分配之后,就會有一部分內存redis無法正常回收,一直占用着。

----------------------------------------------------- 分割線 ------------------------------------------------

知道了原因就可以解決問題了,網上找到了兩個解決方案:
1、重啟redis服務,簡單粗暴。
2、redis4.0以上可以使用新增指令來手動回收內存碎片,配置監控使用性能更佳,具體大家可以自己去查。

這里提個問題,如果是單機redis,想要不停服務重啟redis,大家有什么好的想法?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM