Redis刪除策略和逐出策略

本文知識點
過期數據概念
數據刪除策略
逐出算法

過期數據

先來看三個key值,分別爲sex、name、age。

這三個值設置的指令爲 set name kaka setex age 100 24 setex sex 10 1

在這裏插入圖片描述
在redis中我們可以使用ttl來獲取某個key的狀態,下面我們來使用ttl分別獲取一下上邊name、age、sex的狀態

可以看到出來了三個值,分別爲 -1 775 -2

那麼這三個值給出的信息是什麼呢!

  • -1 表示永久有效的數據
  • 775 這個值是設置在age上,使用的指令爲setex age 1000 24,表示爲剩餘有效時間
  • -2 表示已經過期的數據,或者是被刪除的數據,或者說是麼有定義的數據
    在這裏插入圖片描述

過期數據的存儲結構

  • 當我們設置一個帶有時效性的name時,redis存儲的是一個內存地址0x10101
  • 然後redis會再開闢一個空間用來存儲帶有時效性的key
  • 但是存儲方式是key對應的內存地址 和 過期時間
    在這裏插入圖片描述
    那麼今天我們所說的redis刪除策略,就是刪除的這部分數據。

定時刪除

定時刪除就是寫一個定時器,然後當key的時間過期後,定時器任務立即對過期的key進行刪除

優點:可想而知key到期就刪,肯定對內存時最友好的,節約內存

缺點:redis單線程的特性是所有的命令都在按照一定的順序進行執行。key值到期就刪cpu的壓力就會變大,會直接影響到redis服務器響應時間和IO

定時刪除就是用時間來換取空間

當執行完定時刪除後,key值對應的數據會被刪除,同時在過期的內存區裏邊也會直接刪除。
在這裏插入圖片描述

惰性刪除

在來看這個圖當key值過期後不會直接刪除,那是什麼時候刪除呢!繼續往下看
在這裏插入圖片描述

當我們使用惰性刪除時,數據到期了也不會自動刪除,那麼他的刪除方式是,在下一次在獲取這個key值時,會做一個判斷,判斷這個key是否過期,如果過期了在執行刪除。

也就是說當再次執行get name時 會走一個函數expirelfNeeded() 這個函數就是判斷此key是否過期的。過期的返回nil,然後從內存在進行刪除

在這裏插入圖片描述
優點:會減少一定的CPU性能,只有到必須要刪的時候纔會刪除

缺點:那肯定就是內存壓力大了,例如一些熱點新聞,熱點過了就基本沒人訪問了,沒有人訪問這個key就一直存在,就會出現長期佔用一定的內存空間

也就說這種方式是用空間換時間

定期刪除

在上文中我們提及了倆種刪除方式,一種是定時刪除,一種是惰性刪除。一個是用空間換時間。一個是用時間換空間。倆種方案都是比較極端的方式。那麼接下來我們在來看看定期刪除的實現方案。

先來看一下redis的存儲空間,一共有默認爲16個,在redis.conf裏邊有一個配置參數database這個參數控制的。每個數據庫都有自己的過期分區,裏邊存儲就是數據地址 和 數據過期時間。

在這裏插入圖片描述
實現方式

redis在啓動時,會取讀取server下的hz的值,默認爲10。這個值直接在終端使用info server就可以查看的到

在這裏插入圖片描述
然後會每秒鐘執行server下hz次 進行serverCron()輪詢

繼續使用databasesCron對redis的16個庫進行挨個訪問信息

訪問時候會再執行activeExpireCycel對每個expires[*]逐一進行檢測,每個執行的時間爲250ms / server hz這個參數

在對每個expirs[*]逐一檢測時,會隨機拿出ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC個可以進行檢測

  • 如果key超時,直接刪除key
  • 一輪中刪除的key數量>ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC*25%繼續循環該過程
  • 如果一輪中刪除的key數量<=ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC25% ,檢查下一個expires[]

那麼現在問題來了,我們的250ms / hz這個時間執行完了,但是把expires的16個數據庫沒有循環完怎麼辦呢! 下次來在循環那個庫呢! 其實這個值是有存的,就是current_db這個值。這個值會記錄activeExpireCycel 下次進入那個expires[*]執行
在這裏插入圖片描述
特點1:CPU使用沒有高峯值,檢測頻率自定義設置

特點2:內存壓力不會很大, 長時間佔用的內存會被持續的清理

逐出算法

在上文中我們說了三種刪除策略,但是這三種策略都是相對於設置了有效期的key纔會有效。

那現在我們的redis使用的內存不足了,就會使用逐出策略來保證redis的正常使用。

redis在每次執行命令前會調用freeMemorylfNeeded()檢測內存是否充足,當不充足時就會清理一些key,這種清除數據的策略稱爲逐出策略。

redis最大可使用內存的參數爲:maxmemory 默認爲0 指的是佔用物理內存的比例 一般設置50%就可以了

每次選取待刪除key的個數:maxmemory-samples

刪除策略:maxmemory-policy

下面我們來着重說明刪除策略

  • 檢測易失數據(也就是我們設置了有效期,但是還沒有到期的數據,就是上文expires[*])
    • volatile-lru:挑選最近少使用的數據
    • volatile-lfu:挑選最近使用次數最少的數據
    • volatile-ttl:挑選將要淘汰的數據
    • volatile-random:隨機選擇

接下來看一幅圖

  • 9s就是現在的時間

  • 距離9s最長的一個key就是age

  • 使用次數最少的就是gender這個key

  • 如果按照volatile-lru就會把age刪除掉

  • 如果按照volatile-lfu就會把gender刪除掉
    在這裏插入圖片描述

  • 檢測全部數據

    • allkeys-lru:挑選最近少使用的數據
    • allkeys-lfu:挑選最近使用次數最少的數據
    • allkeys-random:全庫隨機刪除
  • 放棄數據驅逐

    • no-enviction : 數據不會進行任何的刪除,直到內存用完,引發oom錯誤。

總結

以上就是redis對數據的刪除策略和逐出策略。

這裏就一個注意點就是在逐出策略中,易失數據指的是設置了過期時間的key,並非永久性的值。

全庫是指的全部的值,設置了過期時間和永久數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章