溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

關(guān)于Redis緩存失效機(jī)制的介紹

發(fā)布時(shí)間:2020-04-07 11:29:11 來源:億速云 閱讀:128 作者:小新 欄目:關(guān)系型數(shù)據(jù)庫

今天小編給大家分享的是關(guān)于Redis緩存失效機(jī)制的介紹,很多人都不太了解,今天小編為了讓大家更加了解Redis緩存失效機(jī)制,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。

Redis緩存失效的故事要從EXPIRE這個(gè)命令說起,EXPIRE允許用戶為某個(gè)key指定超時(shí)時(shí)間,當(dāng)超過這個(gè)時(shí)間之后key對(duì)應(yīng)的值會(huì)被清除,這篇文章主要在分析Redis源碼的基礎(chǔ)上站在Redis設(shè)計(jì)者的角度去思考Redis緩存失效的相關(guān)問題。

關(guān)于Redis緩存失效機(jī)制的介紹

Redis緩存失效機(jī)制

Redis緩存失效機(jī)制是為應(yīng)對(duì)緩存應(yīng)用的一種很常見的場(chǎng)景而設(shè)計(jì)的,講個(gè)場(chǎng)景:

我們?yōu)榱藴p輕后端數(shù)據(jù)庫的壓力,很開心的借助Redis服務(wù)把變化頻率不是很高的數(shù)據(jù)從DB load出來放入了緩存,因此之后的一段時(shí)間內(nèi)我們都可以直接從緩存上拿數(shù)據(jù),然而我們又希望一段時(shí)間之后,我們?cè)僦匦碌膹腄B load出當(dāng)前的數(shù)據(jù)放入緩存,這個(gè)事情怎么做呢?

問題提出來了,這個(gè)問題怎么解決呢?好吧,我們對(duì)于手頭的語言工具很熟悉,堅(jiān)信可以很快的寫出這么一段邏輯:我們記錄上次從db load數(shù)據(jù)的時(shí)間,然后每次響應(yīng)服務(wù)的時(shí)候都去判斷時(shí)間是不是過期了,要不要從db重新load了……。當(dāng)然這種方法也是可以的,然而當(dāng)我們查閱Redis command document的時(shí)候,發(fā)現(xiàn)我們做了本來不需要做的事情,Redis本身提供這種機(jī)制,我們只要借助EXPIRE命令就可以輕松的搞定這件事情:

EXPIRE key 30

上面的命令即為key設(shè)置30秒的過期時(shí)間,超過這個(gè)時(shí)間,我們應(yīng)該就訪問不到這個(gè)值了,到此為止我們大概明白了什么是緩存失效機(jī)制以及緩存失效機(jī)制的一些應(yīng)用場(chǎng)景,接下來我們繼續(xù)深入探究這個(gè)問題,Redis緩存失效機(jī)制是如何實(shí)現(xiàn)的呢?

延遲失效機(jī)制

延遲失效機(jī)制即當(dāng)客戶端請(qǐng)求操作某個(gè)key的時(shí)候,Redis會(huì)對(duì)客戶端請(qǐng)求操作的key進(jìn)行有效期檢查,如果key過期才進(jìn)行相應(yīng)的處理,延遲失效機(jī)制也叫消極失效機(jī)制。我們看看t_string組件下面對(duì)get請(qǐng)求處理的服務(wù)端端執(zhí)行堆棧:

getCommand 
     -> getGenericCommand 
            -> lookupKeyReadOrReply 
                   -> lookupKeyRead 
                         -> expireIfNeeded

關(guān)鍵的地方是expireIfNeed,Redis對(duì)key的get操作之前會(huì)判斷key關(guān)聯(lián)的值是否失效,這里先插入一個(gè)小插曲,我們看看Redis中實(shí)際存儲(chǔ)值的地方是什么樣子的:

typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    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;    long long avg_ttl;          /* Average TTL, just for stats */} redisDb;

上面是Redis中定義的一個(gè)結(jié)構(gòu)體,dict是一個(gè)Redis實(shí)現(xiàn)的一個(gè)字典,也就是每個(gè)DB會(huì)包括上面的五個(gè)字段,我們這里只關(guān)心兩個(gè)字典,一個(gè)是dict,一個(gè)是expires:

dict是用來存儲(chǔ)正常數(shù)據(jù)的,比如我們執(zhí)行了set key "hahaha",這個(gè)數(shù)據(jù)就存儲(chǔ)在dict中。

expires使用來存儲(chǔ)關(guān)聯(lián)了過期時(shí)間的key的,比如我們?cè)谏厦娴幕A(chǔ)之上有執(zhí)行的expire key 1,這個(gè)時(shí)候就會(huì)在expires中添加一條記錄。

回過頭來看看expireIfNeeded的流程,大致如下:

從expires中查找key的過期時(shí)間,如果不存在說明對(duì)應(yīng)key沒有設(shè)置過期時(shí)間,直接返回。

如果是slave機(jī)器,則直接返回,因?yàn)镽edis為了保證數(shù)據(jù)一致性且實(shí)現(xiàn)簡(jiǎn)單,將緩存失效的主動(dòng)權(quán)交給Master機(jī)器,slave機(jī)器沒有權(quán)限將key失效。

如果當(dāng)前是Master機(jī)器,且key過期,則master會(huì)做兩件重要的事情:1)將刪除命令寫入AOF文件。2)通知Slave當(dāng)前key失效,可以刪除了。

master從本地的字典中將key對(duì)于的值刪除。

主動(dòng)失效機(jī)制

主動(dòng)失效機(jī)制也叫積極失效機(jī)制,即服務(wù)端定時(shí)的去檢查失效的緩存,如果失效則進(jìn)行相應(yīng)的操作。

我們都知道Redis是單線程的,基于事件驅(qū)動(dòng)的,Redis中有個(gè)EventLoop,EventLoop負(fù)責(zé)對(duì)兩類事件進(jìn)行處理:

一類是IO事件,這類事件是從底層的多路復(fù)用器分離出來的。

一類是定時(shí)事件,這類事件主要用來事件對(duì)某個(gè)任務(wù)的定時(shí)執(zhí)行。

看起來Redis的EventLoop和Netty以及JavaScript的EventLoop功能設(shè)計(jì)的大概類似,一方面對(duì)網(wǎng)絡(luò)I/O事件處理,一方面還可以做一些小任務(wù)。

為什么講到Redis的單線程模型,因?yàn)镽edis的主動(dòng)失效機(jī)制邏輯是被當(dāng)做一個(gè)定時(shí)任務(wù)來由主線程執(zhí)行的,相關(guān)代碼如下:

if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
        redisPanic("Can't create the serverCron time event.");        
       exit(1);
    }

serverCron就是這個(gè)定時(shí)任務(wù)的函數(shù)指針,adCreateTimeEvent將serverCron任務(wù)注冊(cè)到EventLoop上面,并設(shè)置初始的執(zhí)行時(shí)間是1毫秒之后。接下來,我們想知道的東西都在serverCron里面了。serverCron做的事情有點(diǎn)多,我們只關(guān)心和本篇內(nèi)容相關(guān)的部分,也就是緩存失效是怎么實(shí)現(xiàn)的,我認(rèn)為看代碼做什么事情,調(diào)用堆棧還是比較直觀的:

aeProcessEvents
    ->processTimeEvents
        ->serverCron 
             -> databasesCron 
                   -> activeExpireCycle 
                           -> activeExpireCycleTryExpire

EventLoop通過對(duì)定時(shí)任務(wù)的處理,觸發(fā)對(duì)serverCron邏輯的執(zhí)行,最終之執(zhí)行key過期處理的邏輯,值得一提的是,activeExpireCycle邏輯只能由master來做。

更多redis知識(shí)請(qǐng)關(guān)注redis入門教程欄目。

以上就是關(guān)于Redis緩存失效機(jī)制的簡(jiǎn)略介紹,當(dāng)然詳細(xì)使用上面的不同還得要大家自己使用過才領(lǐng)會(huì)。如果想了解更多,歡迎關(guān)注億速云行業(yè)資訊頻道哦!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI