十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這篇文章主要介紹“redis的過期時(shí)間和過期刪除機(jī)制原理”,在日常操作中,相信很多人在redis的過期時(shí)間和過期刪除機(jī)制原理問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”redis的過期時(shí)間和過期刪除機(jī)制原理”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián)公司不只是一家網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司;我們對(duì)營銷、技術(shù)、服務(wù)都有自己獨(dú)特見解,公司采取“創(chuàng)意+綜合+營銷”一體化的方式為您提供更專業(yè)的服務(wù)!我們經(jīng)歷的每一步也許不一定是最完美的,但每一步都有值得深思的意義。我們珍視每一份信任,關(guān)注我們的成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)質(zhì)量和服務(wù)品質(zhì),在得到用戶滿意的同時(shí),也能得到同行業(yè)的專業(yè)認(rèn)可,能夠?yàn)樾袠I(yè)創(chuàng)新發(fā)展助力。未來將繼續(xù)專注于技術(shù)創(chuàng)新,服務(wù)升級(jí),滿足企業(yè)一站式全網(wǎng)營銷推廣需求,讓再小的成都品牌網(wǎng)站建設(shè)也能產(chǎn)生價(jià)值!
redis有四種命令可以用于設(shè)置鍵的生存時(shí)間和過期時(shí)間:
EXPIRE: 將鍵的生存時(shí)間設(shè)為 ttl 秒 PEXPIRE :將鍵的生存時(shí)間設(shè)為 ttl 毫秒EXPIREAT :將鍵的過期時(shí)間設(shè)為 timestamp 所指定的秒數(shù)時(shí)間戳PEXPIREAT : 將鍵的過期時(shí)間設(shè)為 timestamp 所指定的毫秒數(shù)時(shí)間戳.
那么redis里面對(duì)這些key的過期時(shí)間和生存時(shí)間的信息是怎么保存的呢??
答:在數(shù)據(jù)庫結(jié)構(gòu)redisDb中的expires字典中保存了數(shù)據(jù)庫中所有鍵的過期時(shí)間,我們稱expire這個(gè)字典為過期字典。
(1)過期字典是一個(gè)指針,指向鍵空間的某個(gè)鍵對(duì)象。
(2)過期字典的值是一個(gè)longlong類型的整數(shù),這個(gè)整數(shù)保存了鍵所指向的數(shù)據(jù)庫鍵的過期時(shí)間–一個(gè)毫秒級(jí)的 UNIX 時(shí)間戳。
下圖是一個(gè)帶過期字典的數(shù)據(jù)庫例子:

過期字典是存儲(chǔ)在redisDb這個(gè)結(jié)構(gòu)里的:
typedef struct redisDb { ... dict *dict; //數(shù)據(jù)庫鍵空間,保存著數(shù)據(jù)庫中所有鍵值對(duì) dict *expires // 過期字典,保存著鍵的過期時(shí)間 ...} redisDb; 從以上結(jié)構(gòu)中可以看到expire字典(過期字典)和dict字典(數(shù)據(jù)庫鍵空間,保存著數(shù)據(jù)庫中所有鍵值對(duì))是并列的,由此可見expire字典的重要性。
PERSIST 命令可以移除一個(gè)鍵的過期時(shí)間:
127.0.0.1:6379> set message "hello"OK127.0.0.1:6379> expire message 60(integer) 1127.0.0.1:6379> ttl message(integer) 54127.0.0.1:6379> persist message(integer) 1127.0.0.1:6379> ttl message(integer) -1
persist命令就是expire命令的反命令,這個(gè)函數(shù)在過期字典中查找給定的鍵,并從過期字典中移除。
比如在數(shù)據(jù)庫當(dāng)前狀態(tài)(如上圖所示),當(dāng)給book這個(gè)key移除過期時(shí)間:
redis> persist book(integer) 1
數(shù)據(jù)庫將更新成如下狀態(tài):

可以從圖中看到,當(dāng)PERSIST book命令執(zhí)行之后,過期字典中的 book 鍵消失了。
ttl命令以秒為單位返回指定鍵的剩余生存時(shí)間。pttl以毫秒返回。兩個(gè)命令都是通過計(jì)算當(dāng)前時(shí)間和過期時(shí)間的差值得到剩余生存期的。
127.0.0.1:6379> set minping shuxinOK127.0.0.1:6379> expire minping 60(integer) 1127.0.0.1:6379> ttl minping(integer) 57127.0.0.1:6379> ttl minping(integer) 27127.0.0.1:6379> pttl minping(integer) 23839127.0.0.1:6379>
redis源碼為:
void ttlCommand(redisClient *c) { ttlGenericCommand(c, 0);}void pttlCommand(redisClient *c) { ttlGenericCommand(c, 1);}void ttlGenericCommand(redisClient *c, int output_ms) { long long expire, ttl = -1; /* 如果鍵不存在,返回-2 */ if (lookupKeyRead(c->db,c->argv[1]) == NULL) { addReplyLongLong(c,-2); return; } /* 如果鍵存在*/ /*如果沒有設(shè)置生存時(shí)間,返回 -1, 否則返回實(shí)際剩余時(shí)間 */ expire = getExpire(c->db,c->argv[1]); if (expire != -1) { /* 過期時(shí)間減去當(dāng)前時(shí)間,就是鍵的剩余時(shí)間*/ ttl = expire-mstime(); if (ttl < 0) ttl = 0; } if (ttl == -1) { addReplyLongLong(c,-1); } else { /*將毫秒轉(zhuǎn)化為秒*/ addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000)); }} 如果一個(gè)鍵是過期的,那它到了過期時(shí)間之后是不是馬上就從內(nèi)存中被被刪除呢??如果不是,那過期后到底什么時(shí)候被刪除呢??
其實(shí)有三種不同的刪除策略:
(1):立即刪除。在設(shè)置鍵的過期時(shí)間時(shí),創(chuàng)建一個(gè)回調(diào)事件,當(dāng)過期時(shí)間達(dá)到時(shí),由時(shí)間處理器自動(dòng)執(zhí)行鍵的刪除操作。
(2):惰性刪除。鍵過期了就過期了,不管。每次從dict字典中按key取值時(shí),先檢查此key是否已經(jīng)過期,如果過期了就刪除它,并返回nil,如果沒過期,就返回鍵值。
(3):定時(shí)刪除。每隔一段時(shí)間,對(duì)expires字典進(jìn)行檢查,刪除里面的過期鍵。
可以看到,第二種為被動(dòng)刪除,第一種和第三種為主動(dòng)刪除,且第一種實(shí)時(shí)性更高。下面對(duì)這三種刪除策略進(jìn)行具體分析。
立即刪除能保證內(nèi)存中數(shù)據(jù)的最大新鮮度,因?yàn)樗WC過期鍵值會(huì)在過期后馬上被刪除,其所占用的內(nèi)存也會(huì)隨之釋放。但是立即刪除對(duì)cpu是最不友好的。因?yàn)閯h除操作會(huì)占用cpu的時(shí)間,如果剛好碰上了cpu很忙的時(shí)候,比如正在做交集或排序等計(jì)算的時(shí)候,就會(huì)給cpu造成額外的壓力。
而且目前redis事件處理器對(duì)時(shí)間事件的處理方式--無序鏈表,查找一個(gè)key的時(shí)間復(fù)雜度為O(n),所以并不適合用來處理大量的時(shí)間事件。
惰性刪除是指,某個(gè)鍵值過期后,此鍵值不會(huì)馬上被刪除,而是等到下次被使用的時(shí)候,才會(huì)被檢查到過期,此時(shí)才能得到刪除。所以惰性刪除的缺點(diǎn)很明顯:浪費(fèi)內(nèi)存。dict字典和expires字典都要保存這個(gè)鍵值的信息。
舉個(gè)例子,對(duì)于一些按時(shí)間點(diǎn)來更新的數(shù)據(jù),比如log日志,過期后在很長的一段時(shí)間內(nèi)可能都得不到訪問,這樣在這段時(shí)間內(nèi)就要拜拜浪費(fèi)這么多內(nèi)存來存log。這對(duì)于性能非常依賴于內(nèi)存大小的redis來說,是比較致命的。
從上面分析來看,立即刪除會(huì)短時(shí)間內(nèi)占用大量cpu,惰性刪除會(huì)在一段時(shí)間內(nèi)浪費(fèi)內(nèi)存,所以定時(shí)刪除是一個(gè)折中的辦法。
定時(shí)刪除是:每隔一段時(shí)間執(zhí)行一次刪除操作,并通過限制刪除操作執(zhí)行的時(shí)長和頻率,來減少刪除操作對(duì)cpu的影響。另一方面定時(shí)刪除也有效的減少了因惰性刪除帶來的內(nèi)存浪費(fèi)。
redis使用的過期鍵值刪除策略是:惰性刪除加上定期刪除,兩者配合使用。
到此,關(guān)于“redis的過期時(shí)間和過期刪除機(jī)制原理”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!