Redis內部通過兩種主要策略來處理過期的Key:
惰性刪除
惰性刪除:顧明思議并不是在TTL到期后就立刻刪除,而是在訪問一個key的時候,Redis會先檢查這個鍵是否過期。如果過期,就刪除它,然后返回nil
。
這種方式非常節省CPU,因為只有在必要時才進行檢查。但是如果一個過期的鍵一直不被訪問,它就會一直占用內存,造成“內存泄漏”。
周期刪除
為了彌補惰性刪除的不足,Redis需要一個機制來主動發現并清理那些“被遺忘”的過期鍵。周期性刪除就是為此而生的。
周期刪除:顧明思議是通過一個定時任務,周期性的抽樣部分過期的key,然后執行刪除。執行周期有兩種:
- FAST模式:Redis的每個事件循環前會調用beforeSleep()函數,遍歷過期字典,執行過期key清理,
- SLOW模式:Redis服務初始化函數initServer()中設置定時任務,按照server.hz的頻率來執行過期key清理,
SLOW模式規則:
- 執行頻率受server.hz影響,默認為10,即每秒執行10次,每個執行周期100ms。
- 執行清理耗時不超過一次執行周期的25%.默認slow模式耗時不超過25ms
- 逐個遍歷db,逐個遍歷db中的bucket,抽取20個key判斷是否過期
- 如果沒達到時間上限(25ms)并且過期key比例大于10%,再進行一次抽樣,否則結束
- FAST模式規則(過期key比例小于10%不執行 ):
- 執行頻率受beforeSleep()調用頻率影響,但兩次FAST模式間隔不低于2ms
- 執行清理耗時不超過1ms
- 逐個遍歷db,逐個遍歷db中的bucket,抽取20個key判斷是否過期
如果沒達到時間上限(1ms)并且過期key比例大于10%,再進行一次抽樣,否則結束
總結:
惰性清理:每次查找key時判斷是否過期,如果過期則刪除
定期清理:定期抽樣部分key,判斷是否過期,如果過期則刪除。
定期清理的兩種模式:
-
SLOW模式執行頻率默認為10,每次不超過25ms
-
FAST模式執行頻率不固定,但兩次間隔不低于2ms,每次耗時不超過1ms