redis探析

Redis (REmote DIctionary Server) 是一個由Salvatore Sanfilippo寫的key-value存儲系統。 

Redis過期鍵刪除策略

redisDb 結果的 expires 字典保存了數據庫中所有鍵的過期時間,我們稱這個字典爲過期字典

  • 過期字典的鍵是一個指針,這個指針指向鍵空間的某個鍵對象
  • 過期字典的值是一個 long long 類型的證書,用於保存毫秒精度的 UNIX 時間戳

過期鍵刪除策略的三種方案

  • 定時刪除: 在設置鍵的過期時間的同時,創建一個定時器,讓定時器執行對鍵的刪除操作
  • 惰性刪除: 每次取的時候先判斷 expires 對象裏面的鍵是否已經過期,如果過期,則刪除鍵,否則,返回該鍵
  • 定期刪除: 每隔一段時間,程序對數據庫遍歷檢查一遍,然後刪除過期的鍵

定時刪除

定時刪除策略對內存最友好,通過使用定時器,定時刪除策略可以保證鍵在過期時間一定會被刪除,刪除後就釋放該鍵之前佔用的內存。但是,定時刪除策略的缺點是,它對 CPU 時間是最不友好的,在過期鍵比較多的情況下,刪除過期鍵這一行爲可能會佔用相當一部分 CPU 時間,在內存不緊張但是 CPU 時間非常緊張的情況下,將大量 CPU 時間浪費在刪除過期的策略上,而不是用在處理客戶端的請求上,毫無疑問是不行的。

惰性刪除

通過定時刪除的描述,你可能會想那用惰性刪除就最好了,這樣就不會浪費 CPU 時間,每次取數據的時候才判斷,如果過期才刪除它,這樣就能騰出大量的 CPU 去處理客戶端請求了。然而,這對內存卻又是最不友好的,因爲這種策略並不能保證所有鍵一定會訪問到,比如說一些取得並不頻繁的數據,就會大量堆積在內存中,如果這些內存得不到釋放,可想而知後果是多麼嚴重。

從上面兩種情況看來,這兩種刪除的方式單一使用的過程都有明顯的缺陷:

  • 定時刪除佔用過多 CPU 時間,影響服務器的響應時間和吞吐量。
  • 惰性刪除浪費過多內存,有內存泄露的風險
    定期策略是兩種策略的一種折中辦法:
  • 定期策略每隔一段時間執行一次刪除過期的操作,並通過限制刪除操作執行的時長和頻率來減少刪除操作對CPU 時間的影響
  • 定期刪除過期鍵能有效的減少過期鍵而造成的內存浪費
    但是,這個問題點在於如何設定刪除操作執行的時長和頻率?設置的太頻繁吧,就又跟定時刪除一樣,浪費大量CPU,設置得長一點吧,這又可能出現內存大量堆積。

Redis所使用的過期刪除策略

Redis實際上使用的是惰性刪除和定期刪除兩種策略,通過配合使用,服務器可以很好的平衡 CPU 和內存。

  • 惰性刪除策略的實現
    每次取數據的時候都會調用過濾函數(db.c/expireIfNeeded),該函數主要用來判斷鍵是否過期,如果過期,則刪除鍵,否則,則取得對應鍵的值。

     

    image.png

定期刪除鍵的策略實現

過期鍵的定期刪除策略由 redis.c/activeExpireCycle函數實現,每當 Redis 的服務器週期性操作 redis.c/serverCron 函數執行時, activeExpireCycle 函數就會被調用,它在規定的時間內分多次遍歷服務器的各個數據庫,檢查數據庫的 expires 字典中部分鍵(相當於分頁查詢)的過期時間,並刪除它。步驟如下:

  • 函數每次運行時,都從一定數量的數據庫取出一定數量的隨機鍵進行檢查,並刪除其中的過期鍵。
  • 全局變量 current_db 會記錄當前 activeExpireCycle 函數的檢查進度,並在下一次 activeExpireCycle 調用時,接着上一次的進度進行處理。
  • 隨着 activeExpireCycle 函數的不斷執行,服務器中的所有數據庫都會被檢查一遍,當到達最後時,把 current_db 設置爲 0,然後又重新開始,如此循環下去。

 

 

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