欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis過期Key刪除策略和內存淘汰策略的實現(xiàn)

 更新時間:2024年02月19日 09:04:19   作者:Surpass余sheng軍  
當內存使用達到上限,就無法存儲更多數(shù)據(jù)了,為了解決這個問題,Redis內部會有兩套內存回收的策略,過期Key刪除策略和內存淘汰策略,本文就來詳細的介紹一下這兩種方法,感興趣的可以了解一下

Redis之所以性能強,最主要的原因就是基于內存存儲,然而單節(jié)點的Redis其內存大小不宜過大,否則會影響持久化或主從同步的性能。

Redis內存滿了,會發(fā)生什么?

  • 在Redis的運行內存達到了某個閾值,就會觸發(fā)內存淘汰機制  =>  防止把內存撐爆,這個閾值就是我們設置的最大運行內存。 

我們可以通過修改redis.conf配置文件來設置Redis的最大內存,配置項為maxmemory:

  • Redis默認情況下是沒有對最大內存大小做限制的,默認情況下Redis就是根據(jù)你當前的服務器里面,當前最多可以申請到的內存大小來去做限制! 
# 格式:
# maxmemory <bytes>
# 例如:
maxmemory 1gb

當內存使用達到上限,就無法存儲更多數(shù)據(jù)了,因此,為了解決這個問題,Redis內部會有兩套內存回收的策略:

  • 內存過期策略
  • 內存淘汰策略

內存過期策略 - 過期key處理 - 過期刪除策略

如何設置過期時間?

  • expire key n秒     
  • pexpire key  n毫秒     
  • set   key  value  ex  n秒   
  • set  key  value nx  n毫秒

查看某個key剩余的存活時間:TTL  key 

  • 我們可以通過expire / EX命令給Redis的key設置TTL(過期時間 / 存活時間),單位:秒,當key的TTL到期以后,即當過期時間到了以后,再次訪問該key時返回的是nil,說明這個Key已經(jīng)不存在了,對應的內存也得到釋放,從而起到內存回收的目的。
# 寫入一條數(shù)據(jù)
set num 123
# 設置20秒過期時間
expire num 20
# 寫入一條數(shù)據(jù)并設置20s過期時間
set num EX 20

Redis是如何知道一個key是否過期呢?

  • Redis本身是一個典型的key-value的鍵值型內存存儲數(shù)據(jù)庫,因此所有的key-value都保存在Dict結構中,在其redisDb結構體中,有兩個Dict,也就是哈希表:一個用來記錄KEY-VALUE鍵值對(當然存的不是真正的Key-Value,存儲的其實是RedisObject對應的內存地址的指針),另一個用來記錄key的TTL。

過期字典存儲在 redisDb 結構中,如下: 

來看下redisDb的底層源碼:

typedef struct redisDb {
    dict dict;                 / The keyspace for this DB , 也就是存放KEY和VALUE的哈希表*/
    dict *expires;              /* 同樣是哈希表,但保存的是設置了TTL的KEY,及其到期時間*/
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS /
    int id;                     / Database ID, 0 ~ 15 /
    long long avg_ttl;          / Average TTL, just for stats /
    unsigned long expires_cursor; / Cursor of the active expire cycle. */
    list *defrag_later;         /* List of key names to attempt to defrag one by one, gradually. */
} redisDb;

每當我們對一個key設置了過期時間后,Redis會把該key帶上過期時間存儲到一個過期字典(expires dict)中,也就是說「過期字典」保存了數(shù)據(jù)庫中所有 key 的過期時間。 

當我們查詢一個 key 時,Redis 首先檢查該 key 是否存在于過期字典中:

  • 如果不在,則正常讀取鍵值;
  • 如果存在,則會獲取該 key 的過期時間,然后與當前系統(tǒng)時間進行比對,如果比系統(tǒng)時間大,那就沒有過期,否則判定該 key 已過期    =>   查詢到對應的TTL,加以判斷即可。

是不是TTL到期就立即刪除了呢? 

TTL(Time To Live)的含義是存活時間。 

  • Redis并不會在Key過期時立刻刪除KEY,因為要實現(xiàn)這樣的效果就必須給每一個過期Key設置一個定時器,并監(jiān)控這些Key的過期狀態(tài),然后去做判斷,在key過期的那一刻給它立刻刪掉   =>  定時刪除它的優(yōu)點就是保證過期key會被盡快刪除,也就是內存可以盡快得到釋放,因此,定時刪除對內存是最友好的;
  • 如果說我們的key比較少那還好,但是如果我們的key非常的多,達到數(shù)十萬甚至數(shù)百萬,那么這些key如果我們都給它設置這樣一個定時器,無論是對CPU還是對內存都會帶來極大的負擔,這樣一來,就會嚴重影響到Redis服務本身的一個性能,所以說這個是沒有辦法接受的,因此,我們在實際應用當中,Redis采用的并不是立即刪除,而是惰性刪除  + 周期刪除  =>   Redis 使用的過期刪除策略是「惰性刪除+定期刪除」這兩種策略配和使用,刪除的對象是已過期的 key。

Redis的過期KEY刪除策略有兩種:

  • 惰性刪除

  • 周期刪除或定期刪除

惰性刪除

  • 顧名思義就是TTL過期后不會立刻刪除,惰性刪除策略的做法是,不主動刪除過期鍵,而是在訪問使用一個key的時候,判斷當前key有沒有設置TTL過期時間,如果有,則檢查該key的存活時間,如果發(fā)現(xiàn)key已經(jīng)過期才執(zhí)行刪除操作,如果沒有過期,不做任何處理,然后返回正常的鍵值對給客戶端。 

惰性刪除策略的優(yōu)缺點:

優(yōu)點:

  • 因為每次訪問時,才會檢查該key是否過期,因此惰性刪除策略可以節(jié)省CPU資源,對CPU時間最友好。

缺點:

  • 如果一個key已經(jīng)過期,而這個key又仍然保留在數(shù)據(jù)庫中,那么只要這個過期key一致沒有被訪問,它所占用的內存就不會釋放,會造成一定的內存空間浪費,所以惰性刪除策略對內存不友好   =>   這不就是會導致內存泄漏嗎???

周期刪除 / 定期刪除策略

  • 顧名思義就是通過一個定時任務,每隔一段時間周期性的從數(shù)據(jù)庫中抽取一定數(shù)量的key進行檢查,并刪除其中的過期key。

Redis默認會每秒進行10次過期檢查(此配置可以通過Redis的配置文件redis.conf進行配置,配置鍵為hz,它的默認值是hz 10),每次檢查數(shù)據(jù)庫并不是遍歷過期字典中的所有key,而是從數(shù)據(jù)庫中隨機抽取一定數(shù)量的key進行過期檢查:

  • 從過期字典中隨機抽取20個key;
  • 檢查這20個key是否過期,并刪除已過期的key;
  • 如果本輪檢查的已過期key的數(shù)量,超過5個(5 / 20 = 1 / 4 = 25%),也就是「已過期 key 的數(shù)量」占比「隨機抽取 key 的數(shù)量」大于 25%,則繼續(xù)隨機抽查,重復步驟1;如果已過期的key的比例小于25%,則停止繼續(xù)刪除過期key,退出本輪檢查,然后等待下一輪再檢查。 

可以看到,定期刪除是一個循環(huán)的流程

Redis為了保證定期刪除不會出現(xiàn)循環(huán)過度,導致線程卡死現(xiàn)象,為此增加了定期刪除循環(huán)流程的時間上限,默認不會超過25ms,超出時間限制則退出。 

定期刪除策略的優(yōu)缺點

優(yōu)點:

  • 定期刪除是Redis的主動刪除策略,它可以確保過期key能夠及時被刪除

缺點:

  • 會占用CPU資源去掃描key,可能會影響到Redis的性能 

可以看到,惰性刪除策略和定期刪除策略都有各自的優(yōu)缺點,所以Redis選擇「惰性刪除+定期刪除」這兩種策略配和使用,以求在合理使用 CPU 時間和避免內存浪費之間取得平衡。 

如果過期鍵沒有被訪問,而定期刪除又跟不上新鍵產(chǎn)生的速度,內存不就慢慢耗盡了嗎? 

內存淘汰策略

內存淘汰:

  • 就是當Redis的內存使用達到設置的閾值時,Redis就會主動挑選部分key刪除以釋放更多內存的流程,這就叫做內存淘汰機制。
  • 內存淘汰策略是解決內存過大的問題。

內存淘汰時機

當內存達到閾值時執(zhí)行內存淘汰,但問題是Redis什么時候會去判斷內存是否達到閾值呢?

  • Redis每次執(zhí)行任何命令時,都會判斷內存是否達到閾值。

當Redis內存不足時會怎么做?

  • 這取決于配置的內存淘汰策略,Redis支持很多種內存淘汰策略,例如LRU、LFU、Random,但默認的策略是直接決絕新的寫入請求,而如果設置了其它策略,則會在每次執(zhí)行命令后判斷內存占用是否達到閾值,如果達到閾值則會基于配置的內存淘汰策略嘗試進行內存淘汰,直到占用內存小于閾值為止。 

Redis 內存淘汰策略有哪些? 

Redis支持內存淘汰,配置參數(shù)maxmemory-policy決定了內存淘汰策略,這個參數(shù)一共有8個枚舉值,也就是說Redis內存淘汰策略共有8種這八種策略大體分為「不進行數(shù)據(jù)淘汰」和「進行數(shù)據(jù)淘汰」兩類策略:

1. 不進行數(shù)據(jù)淘汰的策略

  • noevictionRedis3.0之后,默認的內存淘汰策略) :禁止刪除數(shù)據(jù),它表示當Redis的運行內存超過最大設置內存時,也就是當Redis內存滿時,不淘汰任何鍵值對數(shù)據(jù),而是不再提供服務,不允許寫入新數(shù)據(jù),Redis的寫命令會直接返回錯誤信息(但是讀命令還是可以正常返回)。

2. 進行數(shù)據(jù)淘汰的策略

針對「進行數(shù)據(jù)淘汰」這一類策略,又可以細分為「在設置了過期時間的數(shù)據(jù)中進行淘汰」和「在所有數(shù)據(jù)范圍內進行淘汰」這兩類策略。 在設置了過期時間的數(shù)據(jù)中進行淘汰:

  • volatile-random:隨機淘汰設置了過期時間的任意鍵值 - 從已設置過期時間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰;
  • volatile-ttl從已設置過期時間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰:比較key的剩余TTL值,TTL越小越先被淘汰。
  • volatile-lru(Redis3.0 之前,默認的內存淘汰策略):LRU(Least Recently Used),最近最久未使用,利用LRU算法淘汰所有設置了TTL過期時間的鍵值中,最久未使用的鍵值;
  • volatile-lfu(Redis 4.0 后新增的內存淘汰策略):LFU(Least Frequently Used),最少頻率使用,淘汰所有設置了TTL過期時間的鍵值中,最少使用的鍵值;

在所有數(shù)據(jù)范圍內進行淘汰:

  • allkeys-random:對全體key,隨機進行淘汰;
  • allkeys-lruLRU(Least Recently Used),最近最久未使用,淘汰全體鍵值中最久未使用的鍵值;
  • allkeys-lfuRedis 4.0 后新增的內存淘汰策略)::LFU(Least Frequently Used),最少頻率使用,淘汰整個鍵值中最少使用的鍵值,即訪問頻率最低的那個key-value。

比較容易混淆的有兩個算法:

  • LRU(Least Recently Used),最近最久未使用(根據(jù)訪問時間淘汰),會選擇淘汰最近最少使用的數(shù)據(jù),用當前時間減去最后一次訪問時間,這個值越大則淘汰優(yōu)先級越高。
  • LFU(Least Frequently Used),最少頻率使用(根據(jù)訪問頻率淘汰),LFU 算法是根據(jù)數(shù)據(jù)訪問次數(shù)來淘汰數(shù)據(jù)的,它的核心思想是“如果數(shù)據(jù)過去被訪問多次,那么將來被訪問的頻率也更高”,所以, LFU 算法會統(tǒng)計每個key的訪問頻率,值越小淘汰優(yōu)先級越高。 

Redis 4.0開始支持基于LFU算法的淘汰策略! 

Redis為什么新增了LFU淘汰策略?

為什么Redis 4.0有了LFU?

  • 比如Redis中的一個鍵,之前一直都沒有被訪問過,最近突然被訪問了一次,如果使用LRU淘汰策略就很難被淘汰,因為LRU會把它定義為熱鍵;
  • 而使用LFU淘汰策略該key就可能很快被淘汰,因為LRU優(yōu)先淘汰最近未被使用的,而LFU淘汰的是最近訪問頻率最低的。
  • LFU比LRU淘汰更精確,有助于提升Redis的緩存命中率。 

Redis怎么知道某個KEY的最后一次訪問時間或者是訪問頻率呢? 

  • redisObject結構體當中的lru就是記錄最近一次訪問時間和訪問頻率的,以低8位無符號數(shù)字來記錄邏輯訪問次數(shù)。
  • 邏輯訪問次數(shù)又是怎么回事呢?8位無符號數(shù)字最大才255,訪問次數(shù)超過255怎么辦?

邏輯訪問次數(shù)是如何計算的?

  • 由于記錄訪問次數(shù)的只有8bit,即便是無符號數(shù),最大值只有255,不可能記錄真實的訪問次數(shù),因此LFU的訪問次數(shù)之所以叫做邏輯訪問次數(shù),是因為并不是每次key被訪問都計數(shù),Redis統(tǒng)計的其實是邏輯訪問次數(shù),這其中是一個計算公式,會根據(jù)當前的訪問次數(shù)做計算,結果要么是次數(shù) + 1,要么是次數(shù)不變,且最大不超過255,除此以外,邏輯訪問次數(shù)還有一個衰減周期,訪問次數(shù)會隨時間衰減,默認為1分鐘,即每隔1分鐘邏輯訪問次數(shù)會 -1,這樣邏輯訪問次數(shù)就能基本反映出一個key的訪問熱度了。

 顯然LFU的基于訪問頻率的統(tǒng)計更符合我們的淘汰目標,因此官方推薦使用LFU算法。 

內存淘汰用到的是LRU算法嗎?

  • 嗯...Redis使用的是近似LRU算法傳統(tǒng)LRU算法的實現(xiàn)需要一個雙向鏈表來記錄數(shù)據(jù)最近被訪問的順序,最新操作的鍵會被移動到表頭,當需要內存淘汰時,只需要刪除鏈表尾部的數(shù)據(jù)即可,因為鏈表尾部的元素就代表最久未被使用的元素。 
  • 但是Redis中的KEY可能有數(shù)百萬甚至更多,出于節(jié)省內存的考慮,Redis的LRU算法并非完整的實現(xiàn),Redis的算法并不是真正的LRU,而是一種基于抽樣的近似LRU算法!
  • Redis采用的是抽樣法,即每次抽樣一定數(shù)量(maxmemory-samples)的key,然后和目前維持的淘汰候選池綜合比較,然后基于內存策略做排序,找出淘汰優(yōu)先級最高的,刪除這個key,這就使得算法的結果更接近于真正的LRU算法了,特別是在抽樣值較高的情況下(例如10),可以達到與真正的LRU接近的結果。

當Redis作為緩存使用的時候,推薦使用allkeys-lru淘汰策略,該策略會將最近最久未使用的key淘汰,像這種key后期命中的概率也最低,所以將其淘汰。 

到此這篇關于Redis過期Key刪除策略和內存淘汰策略的實現(xiàn)的文章就介紹到這了,更多相關Redis過期Key刪除策略和內存淘汰策略內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Redis 命令整理并說明如何使用

    Redis 命令整理并說明如何使用

    這篇文章主要介紹了Redis 命令整理并說明如何使用的相關資料,需要的朋友可以參考下
    2017-02-02
  • Redis的RDB持久化與AOF持久化詳解

    Redis的RDB持久化與AOF持久化詳解

    這篇文章主要介紹了Redis的RDB持久化與AOF持久化詳解,Redis是許多公司都在使用的一款高性能、非關系型數(shù)據(jù)庫,其中最為重要的一個特性就是它支持持久化,本文將深入介紹Redis持久化原理,包括RDB和AOF兩種方式的實現(xiàn),需要的朋友可以參考下
    2023-07-07
  • 基于Redis實現(xiàn)分布式單號及分布式ID(自定義規(guī)則生成)

    基于Redis實現(xiàn)分布式單號及分布式ID(自定義規(guī)則生成)

    一些業(yè)務背景下,業(yè)務要求單號需要有區(qū)分不同的前綴,那么在分布式的架構下如何自定義單號而且還能保證唯一呢?本文就來詳細的介紹一下
    2021-09-09
  • 淺談Redis哨兵模式高可用解決方案

    淺談Redis哨兵模式高可用解決方案

    Redis高可用有兩種模式:哨兵模式和集群模式,本文基于哨兵模式搭建一主兩從三哨兵Redis高可用服務,感興趣的可以了解一下
    2022-03-03
  • redis 限制內存使用大小的實現(xiàn)

    redis 限制內存使用大小的實現(xiàn)

    這篇文章主要介紹了redis 限制內存使用大小的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • redis加鎖的三種方式小結

    redis加鎖的三種方式小結

    本文主要介紹了redis加鎖的三種方式小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • redis分布式鎖的問題與解決方法

    redis分布式鎖的問題與解決方法

    這篇文章主要給大家介紹了關于redis分布式鎖的問題與解決方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用redis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-07-07
  • 淺談Redis的異步機制

    淺談Redis的異步機制

    命令操作、系統(tǒng)配置、關鍵機制、硬件配置等會影響 Redis 的性能,還要提前準備好應對異常的方案,本文主要介紹了Redis的異步機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • 解決 Redis 數(shù)據(jù)傾斜、熱點等問題

    解決 Redis 數(shù)據(jù)傾斜、熱點等問題

    ?單臺機器的硬件配置有上限制約,一般我們會采用分布式架構將多臺機器組成一個集群,這篇文章主要介紹了解決 Redis 數(shù)據(jù)傾斜、熱點等問題,需要的朋友可以參考下
    2022-12-12
  • 深入理解redis刪除策略和淘汰策略

    深入理解redis刪除策略和淘汰策略

    每隔一段時間就掃描一定數(shù)據(jù)的設置了過期時間的key,并清除其中已過期的keys,本文主要介紹了深入理解redis刪除策略和淘汰策略,感興趣的可以了解一下
    2024-08-08

最新評論