1. 程式人生 > 其它 >Redis過期策略與淘汰策略

Redis過期策略與淘汰策略

參加面試連過期策略和淘汰策略概念都傻傻分不清楚

參加了一個面試,面試官問我過期策略有幾種,我TM給人說了幾種淘汰策略,面試官一臉無辜,我還感覺良好

開始正文吧:

1、過期策略(過期鍵的刪除策略):redis使用過程中,很多時候我們會設定一個過期時間,那麼當時間到了的時候,資料會立馬刪除嗎?有可能會,也有可能不會,這就跟過期策略有關了,就是看看redis是如何知道過期的,並且進行的刪除。

  先說結論:有三種

  第一種:定時刪除

    在設定鍵的過期時間的同時,建立一個定時器,讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作。

    優點:對記憶體最友好的。可以及時釋放鍵所佔用的記憶體。

    缺點:對 CPU 不友好。特別在過期鍵比較多的情況下,刪除過期鍵會佔用相當一部分 CPU 時間。同時在記憶體不緊張,CPU 緊張的情況下,將 CPU 用在刪除和當前任務不想關的過期鍵上,

    無疑會對伺服器響應時間和吞吐量造成影響。

   第二種:惰性刪除

    放任鍵過期不管,但是每次從鍵空間中讀寫鍵時,都會檢查取得的鍵是否過期。如果過期就刪除該刪,否則就返回該鍵。(PS:鍵空間是一個儲存了資料庫所有鍵值對的資料結構)

    優點:對 CPU 最友好。只有在操作的時候進行過期檢查,刪除的目標僅限於當前需要處理的鍵,不會在刪除其他無關本次操作的過期鍵上花費任何 CPU 時間。

    缺點:對記憶體不友好。這個十分容易理解了,鍵過期了,但因為一直沒有被訪問到,所以一直保留著(除非手動執行 flushdb 操來於清空當前資料庫中的所有 key。),相當於記憶體洩漏。

   第三種:定期刪除

    每隔一段時間,程式就對資料庫進行檢查,刪除裡面的過期鍵。至於要刪除多少過期鍵,以及檢查多少資料庫,則有演算法決定。該策略是上述兩種策略的折中方案,需要通過實際情況,

    來設定刪除操作的執行時長和頻率。明白了過期鍵的刪除策略後,那 redis 伺服器又是採用什麼策略來刪除過期鍵的呢?實際上,Redis 伺服器使用的是惰性刪除和定期刪除兩種策略,

    通過配合使用,伺服器可以很好的平衡 CPU 和記憶體。其中惰性刪除為 redis 伺服器內建策略。而定期刪除可以通過以下兩種方式設定:

  1. 配置 redis.conf 的 hz 選項,預設為10 (即 1 秒執行 10 次,值越大說明重新整理頻率越快,對 Redis 效能損耗也越大)
  2. 配置 redis.conf 的 maxmemory 最大值,當已用記憶體超過 maxmemory 限定時,就會觸發主動清理策略

2、淘汰策略:當redis使用記憶體超過配置最大記憶體時,如果再有資料插入快取,改如何處理,這就涉及到資料的淘汰策略,和定期刪除中第二點

應該是相同的內容。其實我覺得定期刪除中,不應該加入第二點內容,第二點和淘汰策略就是一回事,應該直接講解淘汰策略就完事了。

  淘汰策略有8中:

    1. no eviction:當記憶體使用超過配置的時候會返回錯誤,不會驅逐任何鍵

    2. allkeys-lru:加入鍵的時候,如果過限,首先通過LRU演算法驅逐最久沒有使用的鍵

    3. volatile-lru:加入鍵的時候如果過限,首先從設定了過期時間的鍵集合中驅逐最久沒有使用的鍵

    4. allkeys-random:加入鍵的時候如果過限,從所有key隨機刪除

    5. volatile-random:加入鍵的時候如果過限,從過期鍵的集合中隨機驅逐

    6. volatile-ttl:從配置了過期時間的鍵中驅逐馬上就要過期的鍵

    7. volatile-lfu:從所有配置了過期時間的鍵中驅逐使用頻率最少的鍵

    8. allkeys-lfu:從所有鍵中驅逐使用頻率最少的鍵

  對LRU做一個簡單說明:

  

    1. 新增key value的時候首先在連結串列結尾新增Node節點,如果超過LRU設定的閾值就淘汰隊頭的節點並刪除掉HashMap中對應的節點。

    2. 修改key對應的值的時候先修改對應的Node中的值,然後把Node節點移動隊尾。

    3. 訪問key對應的值的時候把訪問的Node節點移動到隊尾即可。

  Redis的LRU實現

    Redis維護了一個24位時鐘,可以簡單理解為當前系統的時間戳,每隔一定時間會更新這個時鐘。每個key物件內部同樣維護了一個24位的時鐘,

    當新增key物件的時候會把系統的時鐘賦值到這個內部物件時鐘。比如我現在要進行LRU,那麼首先拿到當前的全域性時鐘,

    然後再找到內部時鐘與全域性時鐘距離時間最久的(差最大)進行淘汰,這裡值得注意的是全域性時鐘只有24位,按秒為單位來表示才能儲存194天,

    所以可能會出現key的時鐘大於全域性時鐘的情況,如果這種情況出現那麼就兩個相加而不是相減來求最久的key。

參考:

https://segmentfault.com/a/1190000017776475

https://zhuanlan.zhihu.com/p/105587132