Redis到期刪除策略
最近線上遇到Redis記憶體達到maxmemory限制後,資料淘汰過慢導致拖慢應用請求的問題。後來仔細看了一下Redis的各種資料淘汰策略,總結一下。
首先,Redis有三種刪除key的時機,它們對應不同的淘汰策略:
1. 當讀/寫一個已經到期的key時,會觸發惰性刪除策略,直接刪除掉這個到期key。
2. 由於惰性刪除策略無法保證冷資料被及時刪掉,所以Redis會定期主動淘汰一批已到期的key。
3. 當前已用記憶體超過maxmemory限定時,觸發主動清理策略。
下面詳細說一下定期主動淘汰策略和主動清理策略,以及它們所對應的配置參數的含義。
• 定期主動淘汰策略
首先,這裡的“定期”指的是Redis定期調用databasesCron()函數時觸發的清理策略,這個週期性頻率由設定檔中的hz參數決定,代表了一秒鐘內,背景工作期望被調用的次數。Redis-3.0.0中的預設值是10,代表每秒鐘調用10次背景工作。
hz調大將會提高Redis主動淘汰的頻率,如果你的Redis儲存中包含很多冷資料佔用記憶體過大的話,可以考慮將這個值調大,但Redis作者建議這個值不要超過100。我們實際線上將這個值調大到100,觀察到CPU會增加2%左右,但對冷資料的記憶體釋放速度確實有明顯的提高(通過觀察keyspace個數和used_memory大小)。
除了主動淘汰的頻率外,Redis對每次淘汰任務執行的最大時間長度也有一個限定,這樣保證了每次主動淘汰不會過多阻塞應用請求,以下是這個限定計算公式:
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */
...
timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;
可以看出timelimit和server.hz是一個倒數的關係,也就是說hz配置越大,timelimit就越小。換句話說是每秒鐘期望的主動淘汰頻率越高,則每次淘汰最長佔用時間就越短。這裡每秒鐘的最長淘汰佔用時間是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰頻率和每次淘汰的最長時間是通過hz參數控制的。
具體的淘汰過程為:在redis.c/activeExpireCycle()函數中,針對每個db有一個迴圈,每次從db->expires集合中隨機取出20個key,如果有超過5個key到期淘汰,則繼續迴圈。也就是說如果超過25%的key到期淘汰,則繼續淘汰,直到隨機抽取的key的到期率低於25%,或者整個迴圈時間超過timelimit的最大限定。則結束整個淘汰過程。
從以上的分析看,當redis中的到期key比率沒有超過25%之前,提高hz可以明顯提高掃描key的最小個數。假設hz為10,則一秒內最少掃描200個key(一秒調用10次*每次最少隨機取出20個key),如果hz改為100,則一秒內最少掃描2000個key;另一方面,如果到期key比率超過25%,則掃描key的個數無上限,但是cpu時間每秒鐘最多佔用250ms。
• maxmemory的主動清理策略
當mem_used記憶體已經超過maxmemory的設定,對於所有的讀寫請求,都會觸發redis.c/freeMemoryIfNeeded(void)函數以清理超出的記憶體。注意這個清理過程是阻塞的,直到清理出足夠的記憶體空間。所以如果在達到maxmemory並且調用方還在不斷寫入的情況下,可能會反覆觸發主動清理策略,導致請求會有一定的延遲。
清理時會根據使用者配置的maxmemory-policy來做適當的清理(一般是LRU或TTL),這裡的LRU或TTL策略並不是針對redis的所有key,而是以設定檔中的maxmemory-samples個key作為樣本池進行抽樣清理。
maxmemory-samples在redis-3.0.0中的預設配置為5,如果增加,會提高LRU或TTL的精準度,redis作者測試的結果是當這個配置為10時已經非常接近全量LRU的精準度了,並且增加maxmemory-samples會導致在主動清理時消耗更多的CPU時間。
建議:
盡量不要觸發maxmemory,最好在mem_used記憶體佔用達到maxmemory的一定比例後,需要考慮調大hz以加快淘汰,或者進行叢集擴容。
如果能夠控制住記憶體,則可以不用修改maxmemory-samples配置;如果Redis本身就作為LRU cache服務(這種服務一般長時間處於maxmemory狀態,由Redis自動做LRU淘汰),可以適當調大maxmemory-samples。
下面關於Redis的文章您也可能喜歡,不妨參考下:
Ubuntu 14.04下Redis安裝及簡單測試
Redis主從複製基本配置
Redis叢集明細文檔
Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis
Redis系列-安裝部署維護篇
CentOS 6.3安裝Redis
Redis安裝部署學習筆記
Redis設定檔redis.conf 詳解
Redis 的詳細介紹:請點這裡
Redis 的:請點這裡
本文永久更新連結地址: