一、前言
在文章開始之前,我先問大家一個問題:當我們使用指令:expire key second
給一個key設定過期時間,過期時間一到,這個key對應的過期資料
真的被伺服器立即刪除了嗎?答案是並不會立即刪除。知道了這個答案,就來看看Redis中如何處理過期的數據。
二、Redis中的資料特徵
Redis是一種記憶體級資料庫,所有資料都存放在記憶體中,記憶體中的資料可以透過TTL指令取得其狀態,有三種狀態:
指示結果 |
#狀態 |
##XX | 具有時效性的資料 |
-1 | 永久有效的資料 |
##-2
已經過期的資料 或被刪除的資料或未定義的資料 |
|
三、時效性資料儲存結構
當我們用指令設定過期資料後,資料對應的位址會放在expires空間中,儲存方式是哈希,儲存的value是過期時間。
四、資料刪除策略
資料刪除策略目標:
在記憶體佔用與CPU佔用之間尋找一種平衡,顧此失彼都會造成整體redis效能的下降,甚至引發伺服器宕機或記憶體外洩
1、定時刪除
#創建一個定時器,當key設定有過期時間,且過期時間到達時,由定時器任務立即執行對鍵的刪除操作
優點:節約內存,到時就刪除,快速釋放不必要的內存佔用
缺點:CPU壓力很大,無論CPU此時負載量多高,均佔用CPU,會影響redis伺服器回應時間與指令吞吐量
2、惰性刪除
3、定期刪除
##流程分析:
- Redis伺服器啟動初始化時,讀取配置server.hz的值,預設為10
- 然後每秒鐘執行10次
serverCron()方法,該方法用來偵測伺服器
serverCron()方法又會呼叫
databasesCron( )方法,該方法是用來遍歷資料庫的,redis預設有16個資料庫,從第一個資料庫開始
- ##databasesCron()
方法又會呼叫activeExpireCycle()
方法,該方法會對每一個expires[*]
逐一進行偵測,每次執行250ms/server.hz;對某個expires [*]
偵測時,隨機挑選W個key偵測
如果偵測到key逾時,則刪除key;如果一輪中刪除的key的數量>W25% ,循環該過程;如果一輪中刪除的key的數量≤W25%,檢查下一個- expires[*]
,0-15循環。其中W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP屬性值
如果activeExpireCycle()執行時間到期,下次再從current_db繼續向下執行 參數current_db用於記錄activeExpireCycle() 進入哪個expires[*] 執行
定時刪除
節約內存,無佔用 |
不分時段佔用CPU資源,頻度高 |
拿時間換空間 |
|
惰性刪除
#記憶體佔用嚴重 |
延時執行,CPU利用率高 |
拿空間換時間 |
|
#會定期刪除##記憶體定期隨機清理 | 每秒花費固定的CPU資源維護記憶體 | 隨機抽查,重點抽查 |
|
六、逐出演算法
1、概念引入
當新資料進入redis時,如果記憶體不足怎麼辦? Redis使用記憶體儲存數據,在執行每個指令前,會呼叫freeMemoryIfNeeded()
偵測記憶體是否足夠。如果記憶體不符合新加入資料的最低儲存需求,redis要暫時刪除一些資料為目前指令清理儲存空間。清理資料的策略稱為逐出演算法。
注意:逐出資料的過程不是100%能夠清理出足夠的可使用的記憶體空間,如果不成功則反覆執行。當所有資料都嘗試完畢後,如果無法達到記憶體清理的要求,將出現錯誤訊息。
2、八種配置
偵測易失資料(可能會過期的資料集server.db[i].expires
)
volatile-lru |
挑選最近最少使用的資料淘汰 |
volatile-lfu |
挑選最近使用次數最少的資料淘汰 |
volatile-ttl |
挑選將要過期的資料淘汰 |
volatile-random |
任意選擇資料淘汰 |
#偵測全庫資料(所有資料集server.db[i].dict
)
allkeys-lru |
挑選最近最少使用的資料淘汰 |
allkeys-lfu |
挑選最近使用次數最少的資料淘汰 |
allkeys-random |
任意選擇資料淘汰 |
放棄資料驅逐:
no-enviction |
禁止驅逐資料(redis4.0中預設策略) |
#
以上是Redis刪除策略的三種方法及逐出演算法實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!