redis數據刪除後,所佔用內存不會立刻還給操做系統,而是交給內存分配管理器,因此對操做系統來講redis仍然佔用着這些內存。html
這裏有個風險點是:redis釋放的內存有多是不連續的,這種不連續的內存極可能沒法再次使用,最終形成了內存的浪費,這種空閒可是沒法使用的內存即是內存碎片。redis
接下來主要介紹redis的內存碎片狀況,產生緣由以及最終的應對方案。ide
能夠經過redis提供的命令來查看redis的內存使用狀況:性能
./redis-cli info memory
執行結果idea
# Memory used_memory:5930032 used_memory_human:5.66M used_memory_rss:8359936 used_memory_rss_human:7.97M ... mem_fragmentation_ratio:1.32
used_memory是redis數據所佔的內存大小。used_memory_rss是操做系統分配給redis的全部內存(包含沒有使用的碎片)。操作系統
mem_fragmentation_ratio= used_memory_rss / used_memory
mem_fragmentation_ratio:線程
jemallco是redis的默認內存分配器,其分配策略不是徹底按照操做系統的按需分配來進行的,而是按照2^n次方的方式來分配,好比8字節,16字節,32字節、2KB,4KB,8KB等,固定大小。code
當redis申請內存時候,jemalloc會分配一個大於所需內存可是最接近2^n的大小,好比須要20字節,jemallo會分配32字節。這樣自然就有12個字節的碎片存在,且沒法避免。htm
jemalloc這種分配方式的好處是減小內存分配的次數,上面的例子中須要20字節,可是分配了32,若是後期再須要10字節,則再也不須要二次分配內存。blog
redis每一個鍵值的大小都不一致,當有內存釋放後有可能過小最終沒法被立刻使用。
上圖中假定A、B、C三塊內存都爲4KB,A被釋放後會有總共有3*4=12KB的內存可用。可是因爲A、B、C不連續,若是這個時候有一個10KB的數據須要分配內存,以上內存是沒法使用的,這就是內存的浪費。
大量的內存碎片會致使內存被浪費,這就須要對內存的碎片進行清理。
重啓是最簡單的辦法,可是重啓後若是沒有開啓rdb或者aof,數據會完全丟失。
若是開啓了持久化機制,恢復須要必定的時間,恢復期間redis自己又不可用。
因此重啓不是第一選擇,比較優雅的辦法是採用redis自身的碎片清理機制。
4.0版本後redis提供了自動內存碎片清理機制。核心思想就是對內存進行搬家合併,讓空閒的內存合併到一塊兒,造成大塊可使用的連續空間。繼續上面的例子。
能夠看到經過碎片整理的內存可以存儲10KB的數據。
開啓碎片自動清理
默認是關閉的。
CONFIG SET activedefrag yes
redis本身的配置說明
特別須要注意的是redis的自動內存碎片清理是由主線程執行的,執行期間沒法處理客戶端請求,這會阻塞redis,影響redis的性能,因此不能頻繁的執行碎片清理。
redis也提供了一些參數用於控制碎片執行的時機和條件。
# The configuration parameters are able to fine tune the behavior of the # defragmentation process. If you are not sure about what they mean it is # a good idea to leave the defaults untouched. # Enabled active defragmentation # activedefrag no # 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, to be used when the lower # threshold is reached # active-defrag-cycle-min 1 # Maximal effort for defrag in CPU percentage, to be used when the upper # threshold is reached # active-defrag-cycle-max 25 # Maximum number of set/hash/zset/list fields that will be processed from # the main dictionary scan # active-defrag-max-scan-fields 1000
redis的上述配置文件也說明了,如非真的有必要,不要開啓碎片清理。
買火車票,好比一班火車只有四個座位,分別在兩排。每一排都連着。
這個時候賣出兩張票,被兩我的買了,分別是第一排的一個座位和第二排的一個座位,剩餘兩個座位。
這時候有人想買兩張連在一排的座位,就買不到了,雖然還有兩個座位,這就是碎片,是浪費。
平時坐火車咱們有時候爲了坐一塊兒,會找協調其餘旅客換座位,這就相似於碎片整理。