Redis系列之記憶體碎片

2021-10-07 22:51:55 字數 3258 閱讀 3696

在使用cachecloud時看到乙個碎片率的監控指標,於是有了此文。

記憶體碎片率,memory fragmentation ratio,簡稱mfr,是redis的乙個效能指標,其計算公式:mfr=used_memory_rss/used_memory

無論是通過redis-cli還是rdm工具,輸入info或者更具體的info memory命令,即可找到/得到如下memory資訊:

used_memory:15288560

used_memory_human:14.58m

used_memory_rss:14237696

used_memory_rss_human:13.58m

mem_fragmentation_ratio:0.93

mem_allocator:jemalloc-3.6.0

輸出引數:

used_memory

已使用的記憶體大小,包括redis程序內部開銷和cache的資料所占用的記憶體,單位byte;human表示可讀資料,單位mb,即除以2^20

used_memory_rss

rss,resident set size,表示redis物理記憶體的大小,即向os申請多少記憶體使用

mem_fragmentation_ratio:

小於1時,表示發生swap,正在使用虛擬記憶體,即可用記憶體不夠,虛擬記憶體其實就是硬碟,效能比記憶體低得多,應該增強機器的記憶體以提高效能

記憶體碎片率略高於1屬於正常,一般超出1.5(待確認?)就說明redis的記憶體管理變差

遠大於1時,表示分配的記憶體超過實際使用的記憶體;數值越大,碎片率越嚴重

mem_allocator:

指定編譯時redis使用的記憶體分配器:libc、jemalloc、tcmalloc,預設是jemalloc。jemalloc在64位系統中,將記憶體空間劃分為小、大、巨大三個範圍;每個範圍內又劃分許多小的記憶體塊單位;儲存資料的時候,會選擇大小最合適的記憶體塊進行儲存。

另外,當記憶體使用量(used_memory)很小的時候,這個值參考價值不大。所以,建議used_memory至少1g以上才考慮對記憶體碎片率進行監控。

碎片整理允許redis壓縮記憶體空間,從而**記憶體。

分析實際環境,因為該redis主要是儲存頻繁更新的資料,每次更新資料之前,redis會刪除舊的資料,實際上,由於redis釋放了記憶體塊,但記憶體分配器並沒有返回記憶體給作業系統,這個記憶體分配器是在編譯時指定的,可以是libc、jemalloc或者tcmalloc。used_memory_rss會越來越大,導致mem_fragmentation_ratio越來越高。

當redis中清理大量的key之後原先redis申請的記憶體(used_memory_rss)將繼續持有而不會釋放,此時檢視記憶體資訊將會看到存在大量的記憶體碎片。

可以這樣認為,redis產生記憶體碎片有兩個原因,

a:redis自身的記憶體分配器。

b:修改cache的值,且修改後的value與原來value的大小差異較大。

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

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

對於redis 4 以前的版本,重啟redis伺服器可以讓額外產生的記憶體碎片失效並重新作為新記憶體來使用,使作業系統恢復高效的記憶體管理;

redis 4+ 版本,

修改記憶體分配器。redis支援glibc』s malloc、jemalloc11、tcmalloc幾種不同的記憶體分配器,每個分配器在記憶體分配和碎片上都有不同的實現。不建議普通管理員修改redis預設記憶體分配器,因為這需要完全理解這幾種記憶體分配器的差異,也要重新編譯redis。

redis4版本之後開始支援記憶體碎片的清理,預設情況下自動清理碎片的引數是關閉的:config get activedefrag應該得到no的輸出,開啟:config set activedefrag yes,再次輸入config get activedefrag驗證輸出是否為yes。

開啟後,後台會啟動程序,也可以手動清理:memory purge

檢視:memory malloc-stats

注:此命令自版本可用。

todo:輸出解讀。。

相關引數配置說明

# enabled active defragmentation

# 碎片整理總開關

# activedefrag yes

# minimum amount of fragmentation waste to start active defrag

# 記憶體碎片達到多少的時候開啟整理

active-defrag-ignore-bytes 100mb

# minimum percentage of fragmentation to start active defrag

# 碎片率達到百分之多少開啟整理

active-defrag-threshold-lower 10

# maximum percentage of fragmentation at which we use maximum effort

# 碎片率小余多少百分比開啟整理

active-defrag-threshold-upper 100

# minimal effort for defrag in cpu percentage

active-defrag-cycle-min 25

# maximal effort for defrag in cpu percentage

active-defrag-cycle-max 75

redis 3.2.9 (整個3版本?)的預設分配器

即libc

redis 4.0 自動記憶體碎片整理(active defrag)原始碼分析

inside of jemalloc

redis效能問題排查解決手冊(七)

Redis系列之 記憶體淘汰策略(筆記)

一 redis 獲取設定的redis能使用的最大記憶體大小 127.0.0.1 6379 10 config get maxmemory 1 maxmemory 2 0 獲取當前記憶體淘汰策略 127.0.0.1 6379 10 config get maxmemory policy 1 maxme...

Redis記憶體碎片率

一 記憶體碎片率 mem fragmentation ratio used memory rss used memory used memory redis使用其分配器分配的記憶體大小 used memory rss 作業系統分配給redis例項的記憶體大小,表示該程序所佔物理記憶體的大小 兩者包括...

Handler系列之記憶體洩漏

本篇簡單的講一下平常使用handler時造成記憶體洩漏的問題。什麼是記憶體洩漏?大白話講就是分配出去的記憶體,不回來。嚴重會導致記憶體不足oom。下面來看一下造成記憶體洩漏的 public class memoryleakactivity extends activity private class...