麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 數(shù)據(jù)庫 > Redis > 正文

Redis中鍵的過期刪除策略深入講解

2020-03-17 12:32:50
字體:
供稿:網(wǎng)友

如果一個(gè)鍵過期了,那么它什么時(shí)候會被刪除呢?

這個(gè)問題有三種可能的答案,它們分別代表了三種不同的刪除策略:

  • 定時(shí)刪除:在設(shè)置鍵的過期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)器( timer ). 讓定時(shí)器在鍵的過期時(shí)間來臨時(shí),立即執(zhí)行對鍵的刪除操作。
  • 惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時(shí),都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵。
  • 定期刪除: 每隔一段時(shí)間,程序就對數(shù)據(jù)庫進(jìn)行一次檢查,刪除里面的過期鍵。至于要?jiǎng)h除多少過期鍵,以及要檢查多少個(gè)數(shù)據(jù)庫, 則由算法決定。

在這三種策略中,第一種和第三種為主動(dòng)刪除策略, 而第二種則為被動(dòng)刪除策略。

前言

使用Redis時(shí)我們可以使用EXPIRE或EXPIREAT命令給key設(shè)置過期刪除時(shí)間,結(jié)構(gòu)體redisDb中的expires字典保存了所有key的過期時(shí)間,這個(gè)字典(dict)的key是一個(gè)指針,指向redis中的某個(gè)key對象,過期字典的value是一個(gè)保存過期時(shí)間的整數(shù)。

/* Redis database representation. There are multiple databases identified * by integers from 0 (the default database) up to the max configured * database. The database number is the 'id' field in the structure. */typedef struct redisDb { dict *dict;     /* The keyspace for this DB */ dict *expires;    /* 過期字典*/ 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 */ struct evictionPoolEntry *eviction_pool; /* Eviction pool of keys */ int id;      /* Database ID */ long long avg_ttl;   /* Average TTL, just for stats */} redisDb;

設(shè)置過期時(shí)間

不論是EXPIRE,EXPIREAT,還是PEXPIRE,PEXPIREAT,底層的具體實(shí)現(xiàn)是一樣的。在Redis的key空間中找到要設(shè)置過期時(shí)間的這個(gè)key,然后將這個(gè)entry(key的指針,過期時(shí)間)加入到過期字典中。

void setExpire(redisDb *db, robj *key, long long when) { dictEntry *kde, *de; /* Reuse the sds from the main dict in the expire dict */ kde = dictFind(db->dict,key->ptr); redisAssertWithInfo(NULL,key,kde != NULL); de = dictReplaceRaw(db->expires,dictGetKey(kde)); dictSetSignedIntegerVal(de,when);}

Redis,鍵,過期刪除,策略

過期刪除策略

如果一個(gè)key過期了,何時(shí)會被刪除呢?在Redis中有兩種過期刪除策略:(1)惰性過期刪除;(2)定期刪除。接下來具體看看。

惰性過期刪除

Redis在執(zhí)行任何讀寫命令時(shí)都會先找到這個(gè)key,惰性刪除就作為一個(gè)切入點(diǎn)放在查找key之前,如果key過期了就刪除這個(gè)key。

Redis,鍵,過期刪除,策略

robj *lookupKeyRead(redisDb *db, robj *key) { robj *val; expireIfNeeded(db,key); // 切入點(diǎn) val = lookupKey(db,key); if (val == NULL)  server.stat_keyspace_misses++; else  server.stat_keyspace_hits++; return val;}

定期刪除

key的定期刪除會在Redis的周期性執(zhí)行任務(wù)(serverCron,默認(rèn)每100ms執(zhí)行一次)中進(jìn)行,而且是發(fā)生Redis的master節(jié)點(diǎn),因?yàn)閟lave節(jié)點(diǎn)會通過主節(jié)點(diǎn)的DEL命令同步過來達(dá)到刪除key的目的。

Redis,鍵,過期刪除,策略

依次遍歷每個(gè)db(默認(rèn)配置數(shù)是16),針對每個(gè)db,每次循環(huán)隨機(jī)選擇20個(gè)(ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)key判斷是否過期,如果一輪所選的key少于25%過期,則終止迭次,此外在迭代過程中如果超過了一定的時(shí)間限制則終止過期刪除這一過程。

for (j = 0; j < dbs_per_call; j++) { int expired; redisDb *db = server.db+(current_db % server.dbnum); /* Increment the DB now so we are sure if we run out of time  * in the current DB we'll restart from the next. This allows to  * distribute the time evenly across DBs. */ current_db++; /* Continue to expire if at the end of the cycle more than 25%  * of the keys were expired. */ do {  unsigned long num, slots;  long long now, ttl_sum;  int ttl_samples;  /* 如果該db沒有設(shè)置過期key,則繼續(xù)看下個(gè)db*/  if ((num = dictSize(db->expires)) == 0) {   db->avg_ttl = 0;   break;  }  slots = dictSlots(db->expires);  now = mstime();  /* When there are less than 1% filled slots getting random   * keys is expensive, so stop here waiting for better times...   * The dictionary will be resized asap. */  if (num && slots > DICT_HT_INITIAL_SIZE &&   (num*100/slots < 1)) break;  /* The main collection cycle. Sample random keys among keys   * with an expire set, checking for expired ones. */  expired = 0;  ttl_sum = 0;  ttl_samples = 0;  if (num > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)   num = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;// 20  while (num--) {   dictEntry *de;   long long ttl;   if ((de = dictGetRandomKey(db->expires)) == NULL) break;   ttl = dictGetSignedIntegerVal(de)-now;   if (activeExpireCycleTryExpire(db,de,now)) expired++;   if (ttl > 0) {    /* We want the average TTL of keys yet not expired. */    ttl_sum += ttl;    ttl_samples++;   }  }  /* Update the average TTL stats for this database. */  if (ttl_samples) {   long long avg_ttl = ttl_sum/ttl_samples;   /* Do a simple running average with a few samples.    * We just use the current estimate with a weight of 2%    * and the previous estimate with a weight of 98%. */   if (db->avg_ttl == 0) db->avg_ttl = avg_ttl;   db->avg_ttl = (db->avg_ttl/50)*49 + (avg_ttl/50);  }  /* We can't block forever here even if there are many keys to   * expire. So after a given amount of milliseconds return to the   * caller waiting for the other active expire cycle. */  iteration++;  if ((iteration & 0xf) == 0) { /* 每迭代16次檢查一次 */   long long elapsed = ustime()-start;   latencyAddSampleIfNeeded("expire-cycle",elapsed/1000);   if (elapsed > timelimit) timelimit_exit = 1;  } // 超過時(shí)間限制則退出  if (timelimit_exit) return;  /* 在當(dāng)前db中,如果少于25%的key過期,則停止繼續(xù)刪除過期key */ } while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);}

總結(jié)

惰性刪除:讀寫之前判斷key是否過期

定期刪除:定期抽樣key,判斷是否過期

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到Redis頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 午夜精品福利视频 | 欧美wwwwww | 久章草在线视频 | 久久国产秒 | 黄色a级片视频 | 欧美大片一级毛片 | 欧美人xx| 永久免费毛片 | 性看小视频 | 久久久久久免费免费 | 久久99综合久久爱伊人 | 免费中文视频 | 亚洲日色| 亚洲一区二区免费 | 国产成人精品区 | 国产一区二区在线观看视频 | 国产一区视频免费观看 | 亚洲视频在线网 | 日本在线播放一区二区三区 | 草久网| 国产91精品一区二区麻豆亚洲 | 免费久久久久 | 欧美日韩高清在线观看 | 一级黄色免费大片 | 天天草天天干天天 | 国产精品成人一区二区三区电影毛片 | 免费的毛片 | 亚洲天堂在线电影 | 久久亚洲精选 | 色人阁在线视频 | 久久综合九色 | 美女黄污视频 | 国产一级一级 | 国产精品一区在线免费观看 | 一级免费特黄视频 | 在线免费观看日韩视频 | 欧美一级电影网 | 俄罗斯16一20sex牲色另类 | 中国女警察一级毛片视频 | 911视频免费版 | 成人三级免费电影 |