1. 程式人生 > >redis- 使用info輕鬆調優-《每日五分鐘搞定大資料》

redis- 使用info輕鬆調優-《每日五分鐘搞定大資料》

本文根據redis的info命令檢視redis的記憶體使用情況以及state狀態,來觀察redis的執行情況以及需要作出的相應優化。

info

1.memory
used_memory:13409011624 #used_memory=實際快取佔用的記憶體+Redis自身執行所佔用的記憶體(如元資料、lua)。
                        #這個值是由Redis使用記憶體分配器分配的記憶體,不包括記憶體碎片浪費的記憶體。
used_memory_rss:13740019719  #從作業系統上顯示已經分配的記憶體總量。
used_memory_peak:13409011624  #記憶體使用的峰值大小
total_system_memory:33567678464  #系統總記憶體
used_memory_lua:37888  #Lua指令碼引擎所使用的記憶體大小。
maxmemory:0  #最大可用記憶體(可配置,預設為total_system_memory)
maxmemory_policy:noeviction  #淘汰機制,noneviction為禁止淘汰資料
mem_fragmentation_ratio:1.02;  #記憶體碎片率
mem_allocator:jemalloc-4.0.3; #編譯時指定的Redis記憶體分配器,可以是libc、jemalloc、tcmalloc。

2.stats
total_commands_processed:3500  #自啟動起Redis服務處理命令的總數

1.used_memory 過大導致的問題

1.1.引發記憶體交換

  當Redis記憶體使用率超過可用記憶體(maxmemory可配置)的95%時,作業系統會進行記憶體與swap空間資料交換。把記憶體中舊的或不再使用的內容寫入硬碟上即Swap分割槽,以便騰出新的實體記憶體給新頁或活動頁(page)使用。 在硬碟上進行讀寫操作要比在記憶體上進行讀寫操作,時間上慢了近5個數量級,記憶體是0.1μs單位、而硬碟是10ms。如果Redis程序上發生記憶體交換,那麼Redis和依賴Redis上資料的應用會受到嚴重的效能影響。

1.2.rdb持久化風險

  在沒有開啟持久化的情況下,redis宕機或者記憶體使用率超過95%會有丟資料的風險

。若使用快照(rdb)持久化,Redis會fork一個子程序把當前記憶體中的資料完全複製一份寫入到硬碟上(fork使用的記憶體和redis當前使用的記憶體會一樣多)。因此若是當前使用記憶體超過可用記憶體的45%時觸發快照功能,那麼此時進行的記憶體交換會變的非常危險(可能會丟失資料)。 倘若在這個時候例項上有大量頻繁的更新操作,問題會變得更加嚴重。

2.避免used_memory 過大

  • 儘可能的使用Hash資料結構

  因為Redis在儲存小於100個欄位的Hash結構上,其儲存效率是非常高的。所以在不需要集合(set)操作或list的push/pop操作的時候,儘可能的使用Hash結構。比如,在一個web應用程式中,需要儲存一個物件表示使用者資訊,使用單個key表示一個使用者,其每個屬性儲存在Hash的欄位裡,這樣要比給每個屬性單獨設定一個key-value要高效的多。 通常情況下倘若有資料使用string結構,用多個key儲存時,那麼應該轉換成單key多欄位的Hash結構。 如上述例子中介紹的Hash結構應包含,單個物件的屬性或者單個使用者各種各樣的資料。Hash結構的操作命令是HSET(key, fields, value)和HGET(key, field),使用它可以儲存或從Hash中取出指定的欄位。

  • 設定key的過期時間

  一個減少記憶體使用率的簡單方法就是,每當儲存物件時確保設定key的過期時間。倘若key在明確的時間週期內使用或者舊key不大可能被使用時,就可以用Redis過期時間命令(expire,expireat, pexpire, pexpireat)去設定過期時間,這樣Redis會在key過期時自動刪除key。 假如你知道每秒鐘有多少個新key-value被建立,那可以調整key的存活時間,並指定閥值去限制Redis使用的最大記憶體。

  • 回收key

  在Redis配置檔案Redis.conf中,通過設定“maxmemory”屬性的值可以限制Redis最大使用的記憶體,修改後重啟例項生效。 也可以使用客戶端命令config set maxmemory 去修改值,這個命令是立即生效的,但會在重啟後會失效,需要使用config rewrite命令去重新整理配置檔案。

  1. 若是啟用了Redis快照功能,應該設定“maxmemory”值為系統可使用記憶體的45%,因為快照時需要一倍的記憶體來複制整個資料集,也就是說如果當前已使用45%,在快照期間會變成95%(45%+45%+5%),其中5%是預留給其他的開銷。
  2. 如果沒開啟快照功能,maxmemory最高能設定為系統可用記憶體的95%。
  • 淘汰策略

  當記憶體使用達到設定的最大閥值時,需要選擇一種key的回收策略,可在Redis.conf配置檔案中修改“maxmemory-policy”屬性值。 若是Redis資料集中的key都設定了過期時間,那麼“volatile-ttl”策略是比較好的選擇。但如果key在達到最大記憶體限制時沒能夠迅速過期,或者根本沒有設定過期時間。那麼設定為“allkeys-lru”值比較合適,它允許Redis從整個資料集中挑選最近最少使用的key進行刪除(LRU淘汰演算法)。

Redis還提供了一些其他淘汰策略,如下:

volatile-lru:使用LRU演算法從已設定過期時間的資料集合中淘汰資料。
volatile-ttl:從已設定過期時間的資料集合中挑選即將過期的資料淘汰。
volatile-random:從已設定過期時間的資料集合中隨機挑選資料淘汰。
allkeys-lru:使用LRU演算法從所有資料集合中淘汰資料。
allkeys-random:從資料集合中任意選擇資料淘汰
no-enviction:禁止淘汰資料。

  通過設定maxmemory為系統可用記憶體的45%或95%(取決於持久化策略)和設定“maxmemory-policy”為“volatile-ttl”或“allkeys-lru”(取決於過期設定),可以比較準確的限制Redis最大記憶體使用率,在絕大多數場景下使用這2種方式可確保Redis不會進行記憶體交換。倘若你擔心由於限制了記憶體使用率導致丟失資料的話,可以設定noneviction值禁止淘汰資料。

3. used_memory_rss 過大解決辦法

  當mem_fragmentation_ratio遠大於1時即used_memory_rss/used_memory(稍大於1正常),說明redis中存在大量的記憶體碎片,一個比較好的解決辦法就是重啟redis,這裡需要注意的是如果用的是aof持久化,那麼重啟之前要進行rewriteaof操作,否則會無效。還有可以指定Redis使用的記憶體分配器,一般管理員不推薦,麻煩而且要重新編譯。

參考:

評論不能及時回覆可直接加公眾號提問或交流,知無不答,謝謝 。 歡迎關注大叔