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

Redis 對過期數(shù)據(jù)的處理方法

 更新時間:2020年10月19日 08:35:54   作者:程序員養(yǎng)成日記  
這篇文章主要介紹了Redis 對過期數(shù)據(jù)的處理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

在 redis 中,對于已經(jīng)過期的數(shù)據(jù),Redis 采用兩種策略來處理這些數(shù)據(jù),分別是惰性刪除和定期刪除

惰性刪除

惰性刪除不會去主動刪除數(shù)據(jù),而是在訪問數(shù)據(jù)的時候,再檢查當(dāng)前鍵值是否過期,如果過期則執(zhí)行刪除并返回 null 給客戶端,如果沒有過期則返回正常信息給客戶端。

它的優(yōu)點是簡單,不需要對過期的數(shù)據(jù)做額外的處理,只有在每次訪問的時候才會檢查鍵值是否過期,缺點是刪除過期鍵不及時,造成了一定的空間浪費。

源碼

robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
 robj *val;

 if (expireIfNeeded(db,key) == 1) {
  /* Key expired. If we are in the context of a master, expireIfNeeded()
   * returns 0 only when the key does not exist at all, so it's safe
   * to return NULL ASAP. */
  if (server.masterhost == NULL) {
   server.stat_keyspace_misses++;
   notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
   return NULL;
  }

  /* However if we are in the context of a slave, expireIfNeeded() will
   * not really try to expire the key, it only returns information
   * about the "logical" status of the key: key expiring is up to the
   * master in order to have a consistent view of master's data set.
   *
   * However, if the command caller is not the master, and as additional
   * safety measure, the command invoked is a read-only command, we can
   * safely return NULL here, and provide a more consistent behavior
   * to clients accessign expired values in a read-only fashion, that
   * will say the key as non existing.
   *
   * Notably this covers GETs when slaves are used to scale reads. */
  if (server.current_client &&
   server.current_client != server.master &&
   server.current_client->cmd &&
   server.current_client->cmd->flags & CMD_READONLY)
  {
   server.stat_keyspace_misses++;
   notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
   return NULL;
  }
 }
 val = lookupKey(db,key,flags);
 if (val == NULL) {
  server.stat_keyspace_misses++;
  notifyKeyspaceEvent(NOTIFY_KEY_MISS, "keymiss", key, db->id);
 }
 else
  server.stat_keyspace_hits++;
 return val;
}

定期刪除

定期刪除:Redis會周期性的隨機測試一批設(shè)置了過期時間的key并進行處理。測試到的已過期的key將被刪除。

具體的算法如下:

  • Redis配置項hz定義了serverCron任務(wù)的執(zhí)行周期,默認(rèn)為10,代表了每秒執(zhí)行10次;
  • 每次過期key清理的時間不超過CPU時間的25%,比如hz默認(rèn)為10,則一次清理時間最大為25ms;
  • 清理時依次遍歷所有的db;
  • 從db中隨機取20個key,判斷是否過期,若過期,則逐出;
  • 若有5個以上key過期,則重復(fù)步驟4,否則遍歷下一個db;
  • 在清理過程中,若達到了25%CPU時間,退出清理過程;

雖然redis的確是不斷的刪除一些過期數(shù)據(jù),但是很多沒有設(shè)置過期時間的數(shù)據(jù)也會越來越多,那么redis內(nèi)存不夠用的時候是怎么處理的呢?這里我們就會談到淘汰策略

Redis內(nèi)存淘汰策略

當(dāng)redis的內(nèi)存超過最大允許的內(nèi)存之后,Redis會觸發(fā)內(nèi)存淘汰策略,刪除一些不常用的數(shù)據(jù),以保證redis服務(wù)器的正常運行

在redis 4.0以前,redis的內(nèi)存淘汰策略有以下6種

  • noeviction:當(dāng)內(nèi)存使用超過配置的時候會返回錯誤,不會驅(qū)逐任何鍵
  • allkeys-lru:加入鍵的時候,如果過限,首先通過LRU算法驅(qū)逐最久沒有使用的鍵
  • volatile-lru:加入鍵的時候如果過限,首先從設(shè)置了過期時間的鍵集合中驅(qū)逐最久沒有使用的鍵
  • allkeys-random:加入鍵的時候如果過限,從所有key隨機刪除
  • volatile-random:加入鍵的時候如果過限,從過期鍵的集合中隨機驅(qū)逐
  • volatile-ttl:從配置了過期時間的鍵中驅(qū)逐馬上就要過期的鍵
  • 在redis 4.0以后,又增加了以下兩種
  • volatile-lfu:從所有配置了過期時間的鍵中驅(qū)逐使用頻率最少的鍵
  • allkeys-lfu:從所有鍵中驅(qū)逐使用頻率最少的鍵

內(nèi)存淘汰策略可以通過配置文件來修改,redis.conf對應(yīng)的配置項是maxmemory-policy 修改對應(yīng)的值就行,默認(rèn)是noeviction

LRU(the least recently used 最近最少使用)算法

如果一個數(shù)據(jù)在最近沒有被訪問到,那么在未來被訪問的可能性也很小,因此當(dāng)空間滿的時候,最久沒有被訪問的數(shù)據(jù)最先被置換(淘汰)

LRU算法通常通過雙向鏈表來實現(xiàn),添加元素的時候,直接插入表頭,訪問元素的時候,先判斷元素是否在鏈表中存在,如果存在就把該元素移動至表頭,所以鏈表的元素排列順序就是元素最近被訪問的順序,當(dāng)內(nèi)存達到設(shè)置閾值時,LRU隊尾的元素由于被訪問的時間線較遠(yuǎn),會優(yōu)先踢出

但是在redis中,并沒有嚴(yán)格實行LRU算法,之所以這樣是因為LRU需要消耗大量的額外內(nèi)存,需要對現(xiàn)有的數(shù)據(jù)結(jié)構(gòu)進行較大的改造,近似LRU算法采用在現(xiàn)有數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)上使用隨機采樣法來淘汰元素,能達到和LRU算法非常近似的效果。Redis的 LRU算法給每個key增加了一個額外的長度為24bit的小字段,記錄最后一次被訪問的時間戳。

redis通過maxmemory-samples 5配置,對key進行采樣淘汰。同時在Redis3.0以后添加了淘汰池進一步提升了淘汰準(zhǔn)確度。

但是LRU算法是存在一定的問題

例如,這表示隨著時間的推移,四個不同的鍵訪問。每個“〜”字符為一秒鐘,而“ |” 最后一行是當(dāng)前時刻。

~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B ~~ B〜|

~~~~~~~~~~ C ~~~~~~~~ C ~~~~~~~~~ C ~~~~~~ |

~~~~~ D ~~~~~~~~~ D ~~~~~~~ D ~~~~~~~~ D |


在上圖中,按照LRU機制刪除的話刪除的順序應(yīng)該是C->A->B->D 其實這并不是我們想要的,因為B被訪問的頻率是最高的,而D被訪問的頻率比較低,所以我們更想讓B保留,把D刪除,所以我們接下來看另一種策略 LFU

**LFU(leastFrequently used 最不經(jīng)常使用)**

如果一個數(shù)據(jù)在最近一段時間內(nèi)很少被訪問到,那么可以認(rèn)為在將來他被訪問到的概率也很小。所以,當(dāng)空間滿時,最小頻率訪問的數(shù)據(jù)最先被淘汰

Redis使用redisObject中的24bit lru字段來存儲lfu字段, 這24bit被分為兩部分:

1:高16位用來記錄訪問時間(單位為分鐘) 

2:低8位用來記錄訪問頻率,簡稱counter

 16 bits  8 bits
 
 +----------------+--------+
 
 Last decr time | LOG_C |

但是counter 8bit很容易就溢出了,技巧是用一個邏輯計數(shù)器,給予概率的對數(shù)計數(shù)器,而不是一個普通的遞增計數(shù)器
```
uint8_t LFULogIncr(uint8_t counter) {
 if (counter == 255) return 255;
 double r = (double)rand()/RAND_MAX;
 double baseval = counter - LFU_INIT_VAL;
 if (baseval < 0) baseval = 0;
 double p = 1.0/(baseval*server.lfu_log_factor+1);
 if (r < p) counter++;
 return counter;
}
```

對應(yīng)的概率分布計算公式為
```
1.0/((counter - LFU_INIT_VAL)*server.lfu_log_factor+1);
```
其中LFU_INIT_VAL為5,其實簡單說就是,越大的數(shù),遞增的概率越低
嚴(yán)格按照LFU算法,時間越久的key,counter越有可能越大,被剔除的可能性就越小。counter只增長不衰減就無法區(qū)分熱點key。為了解決這個問題,redis提供了衰減因子server.lfu_decay_time,其單位為分鐘,計算方法也很簡單,如果一個key長時間沒有訪問那么他的計數(shù)器counter就要減少,減少的值由衰減因子來控制

到此這篇關(guān)于Redis 對過期數(shù)據(jù)的處理方法的文章就介紹到這了,更多相關(guān)Redis過期數(shù)據(jù)的處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis中Scan命令的踩坑實錄

    Redis中Scan命令的踩坑實錄

    這篇文章主要給大家介紹了關(guān)于Redis中Scan命令踩坑的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 詳解利用redis + lua解決搶紅包高并發(fā)的問題

    詳解利用redis + lua解決搶紅包高并發(fā)的問題

    本篇文章主要介紹了利用redis + lua解決搶紅包高并發(fā)的問題 ,詳細(xì)的講訴了需求分析和方案,有興趣的可以了解一下。
    2016-11-11
  • redis使用skiplist跳表的原因解析

    redis使用skiplist跳表的原因解析

    經(jīng)常會有人問這個問題,redis中為什么要使用跳表?這個問題,redis作者已經(jīng)給出過明確答案,今天通過本文再給大家講解下這個問題,對redis?skiplist跳表知識感興趣的朋友一起看看吧
    2022-10-10
  • redis?protocol通信協(xié)議及使用詳解

    redis?protocol通信協(xié)議及使用詳解

    這篇文章主要為大家介紹了redis?protocol通信協(xié)議及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Redis的持久化方式

    Redis的持久化方式

    Redis提供了兩種主要的持久化方式:RDB和AOF,RDB通過定時快照的方式保存數(shù)據(jù)狀態(tài),而AOF記錄每個寫操作以便于重啟時重放,兩者可以結(jié)合使用,且在重啟時AOF文件會被優(yōu)先用于數(shù)據(jù)恢復(fù),RDB快照具有速度快、節(jié)省磁盤空間的優(yōu)點,但可能會丟失最近的數(shù)據(jù)
    2024-10-10
  • Redis緩存lettuce更換為Jedis的實現(xiàn)步驟

    Redis緩存lettuce更換為Jedis的實現(xiàn)步驟

    在springboot中引入spring-boot-starter-data-redis依賴時,默認(rèn)使用的是lettuce,如果不想使用lettuce而是使用Jedis連接池,本文主要介紹了Redis緩存lettuce更換為Jedis的實現(xiàn)步驟,感興趣的可以了解一下
    2024-08-08
  • Redis 鍵值設(shè)計使用總結(jié)

    Redis 鍵值設(shè)計使用總結(jié)

    這篇文章主要介紹了Redis鍵值設(shè)計的使用總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Redis中鍵和數(shù)據(jù)庫通用指令詳解

    Redis中鍵和數(shù)據(jù)庫通用指令詳解

    這篇文章主要為大家介紹了Redis中鍵和數(shù)據(jù)庫通用指令基本操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Redis配置文件代碼講解

    Redis配置文件代碼講解

    在本篇文章里小編給大家整理的是一篇關(guān)于Redis配置文件的說明內(nèi)容,需要的朋友們可以學(xué)習(xí)下。
    2020-03-03
  • redis發(fā)布和訂閱_動力節(jié)點Java學(xué)院整理

    redis發(fā)布和訂閱_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了redis發(fā)布和訂閱的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評論