Redis之key過期定時(shí)器實(shí)現(xiàn)

用Redis時(shí),有用到EXPIRE、PEXPIRE、SETEX之類命令去設(shè)置key的過期時(shí)間。從2.8版開始還可以去做簡(jiǎn)單的定時(shí)器服務(wù)。
原先也沒太具體去了解Redis的過期實(shí)現(xiàn)方式,但心中總覺得有塊石頭沒放下,于是乎開3.0的源碼去翻看了。
過期策略有3種:立即過期、定時(shí)過期、訪問過期(惰性過期)。但看了源碼后,發(fā)現(xiàn)Redis并沒采用立即過期的策略,而是采用 定時(shí)過期訪問過期 混合方式。使用立即過期的話,Linux環(huán)境下在Redis進(jìn)程里會(huì)有很多timerfd,在幾十萬個(gè)Key這種數(shù)量級(jí)開始,對(duì)cpu是很大的負(fù)擔(dān)。

redis.h

在redis.h文件里有redisDb結(jié)構(gòu)體

typedef struct redisDb {
  dict *dict;
  dict *expires;
  ......
}

expires這屬性是存放當(dāng)前db有過期時(shí)間的鍵,使用hash數(shù)據(jù)結(jié)構(gòu)。

定期刪除策略

代碼在redis.c的activeExpireCycle函數(shù),需要傳個(gè)type參數(shù),用以區(qū)分是用“快速模式”還是“正常模式”。
在“正常模式”下,會(huì)遍歷每一個(gè)編號(hào)下的庫(kù),然后最多隨機(jī)獲取20個(gè)帶過期時(shí)間的key(20是宏ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP的默認(rèn)值),倘若key太多則直接return了。接著調(diào)用redis.c/activeExpireCycleTryExpire函數(shù)嘗試去刪除它,能刪除成功則再發(fā)送expired的pub通知給訂閱者即可。定期刪除的定時(shí)時(shí)長(zhǎng)是100ms。

惰性過期

代碼分布在所有讀寫命令里,如SET、GET、TTL、SADD、HGET...等。每次調(diào)用這些命令的實(shí)際執(zhí)行前,都會(huì)調(diào)用db.c/expireIfNeeded函數(shù)來刪除過期鍵,在刪除之前,也會(huì)發(fā)送expired的pub通知。

EXPIRE/PEXPIRE/SETEX的作用?

這幾個(gè)命令的真正作用是設(shè)置過期時(shí)間,如EXPIRE命令的處理在db.c/expireCommand開始,然后將過期時(shí)間單位從秒轉(zhuǎn)換成毫秒,接著判斷是否存在從節(jié)點(diǎn),最后傳播刪除了的expired key(pub del)。在主節(jié)點(diǎn)則設(shè)置過期時(shí)間,是在宏代碼里去設(shè)置值(聯(lián)合體結(jié)構(gòu)),最后在pub expire的通知。

后記

redis是單線程的,但個(gè)人覺得在pub方面可以用另一條線程去處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容