Redis內存碎片

1、什麼是內存碎片

redis數據刪除後,所佔用內存不會立刻還給操做系統,而是交給內存分配管理器,因此對操做系統來講redis仍然佔用着這些內存。html

這裏有個風險點是:redis釋放的內存有多是不連續的,這種不連續的內存極可能沒法再次使用,最終形成了內存的浪費,這種空閒可是沒法使用的內存即是內存碎片。redis

接下來主要介紹redis的內存碎片狀況,產生緣由以及最終的應對方案。ide

2、如何判斷有內存碎片

能夠經過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線程

  1. 大於1可是小於1.5:是相對合理的,碎片化能夠接受,能夠不進行碎片整理。下一節的碎片造成的緣由能夠看出,碎片自己是沒法完全避免的。
  2. 大於1.5碎片化嚴重,超過了50%。這種狀況下須要想辦法對碎片進行整理,下降碎片化綠
  3. 小於1.0:redis數據所佔內存小於操做系統所分配的內存,這不能說沒有碎片,這個時候說明redis的內存發送了swap,有一部分數據被交換到了硬盤,會嚴重影響redis的性能,須要立刻解決的,具體見操做系統swap對redis的影響

3、內存碎片是怎麼造成的

3.1 jemalloc分配機制致使

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

3.2 數據的修改刪除操做致使

redis每一個鍵值的大小都不一致,當有內存釋放後有可能過小最終沒法被立刻使用。

上圖中假定A、B、C三塊內存都爲4KB,A被釋放後會有總共有3*4=12KB的內存可用。可是因爲A、B、C不連續,若是這個時候有一個10KB的數據須要分配內存,以上內存是沒法使用的,這就是內存的浪費。

大量的內存碎片會致使內存被浪費,這就須要對內存的碎片進行清理。

4、如何清理內存碎片

4.1 重啓

重啓是最簡單的辦法,可是重啓後若是沒有開啓rdb或者aof,數據會完全丟失。

若是開啓了持久化機制,恢復須要必定的時間,恢復期間redis自己又不可用。

因此重啓不是第一選擇,比較優雅的辦法是採用redis自身的碎片清理機制。

4.2 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的上述配置文件也說明了,如非真的有必要,不要開啓碎片清理。

5、和現實的類比

買火車票,好比一班火車只有四個座位,分別在兩排。每一排都連着。

這個時候賣出兩張票,被兩我的買了,分別是第一排的一個座位和第二排的一個座位,剩餘兩個座位。

這時候有人想買兩張連在一排的座位,就買不到了,雖然還有兩個座位,這就是碎片,是浪費。

平時坐火車咱們有時候爲了坐一塊兒,會找協調其餘旅客換座位,這就相似於碎片整理。

相關文章
相關標籤/搜索