Redis 使用一個(gè) HashTable 存儲(chǔ)數(shù)據(jù)的過期時(shí)間,把數(shù)據(jù)的 key 與過期時(shí)間相關(guān)聯(lián)鳄虱,這樣就可以通過 key 來查詢數(shù)據(jù)的過期時(shí)間了趣席。
但 Redis 并不會(huì)每時(shí)每刻去檢查數(shù)據(jù)是否過期,因?yàn)檫@樣做效率太低醇蝴。Redis 清除過期數(shù)據(jù)分兩個(gè)階段進(jìn)行,第一個(gè)階段在定時(shí)器中進(jìn)行(serverCron)想罕,第二個(gè)階段在用戶獲取數(shù)據(jù)時(shí)進(jìn)行悠栓。 階段一對內(nèi)存友好,對 CPU 不友好按价。如果過期刪除的鍵比較多的時(shí)候惭适,刪除鍵這一行為會(huì)占用相當(dāng)一部分 CPU 性能,會(huì)對 Redis 的吞吐量造成一定影響楼镐。階段二對 CPU 友好癞志,內(nèi)存不友好。如果很多鍵過期了框产,但在將來很長一段時(shí)間內(nèi)沒有很多客戶端訪問該鍵導(dǎo)致過期鍵不會(huì)被刪除凄杯,占用大量內(nèi)存空間。
在 Redis 的定時(shí)器中秉宿,每隔 100 毫秒便會(huì)調(diào)用 src/redis.c 的 activeExpireCycle 函數(shù)清理過期數(shù)據(jù)戒突。
activeExpireCycle 函數(shù)隨機(jī)獲取一些數(shù)據(jù)的過期時(shí)間,如果當(dāng)前時(shí)間大于數(shù)據(jù)設(shè)定的過期時(shí)間描睦,就把此數(shù)據(jù)從內(nèi)存中刪除膊存。Redis 每次隨機(jī)獲取 10 個(gè)數(shù)據(jù)的過期時(shí)間,如果這 10 個(gè)數(shù)據(jù)中有超過 25% 的數(shù)據(jù)到達(dá)過期時(shí)間(也就是大于等于 3 個(gè)),這個(gè)清理過程會(huì)一直進(jìn)行下去隔崎。目地是可能刪除更多的過期數(shù)據(jù)今艺,節(jié)省內(nèi)存的空間。
用戶使用 get爵卒、hget 等命令獲取數(shù)據(jù)時(shí)虚缎,Redis 調(diào)用 expireIfNeeded 函數(shù)刪除過期的數(shù)據(jù)(但僅限于當(dāng)前獲取的數(shù)據(jù))。該函數(shù)判斷當(dāng)前獲取的數(shù)據(jù)是否過期技潘,如果已經(jīng)過期遥巴,調(diào)用 dbDelete 函數(shù)把它從數(shù)據(jù)庫中刪除。dbDelete函數(shù)除了刪除數(shù)據(jù)外享幽,還會(huì)把數(shù)據(jù)的過期時(shí)間信息刪除铲掐。
因?yàn)樵诙〞r(shí)器中只是隨機(jī)刪除一些過期數(shù)據(jù),不可能把所有的過期數(shù)據(jù)完全刪除值桩。所以在獲取數(shù)據(jù)時(shí)還需要對數(shù)據(jù)進(jìn)行過期判斷摆霉。
當(dāng)內(nèi)存達(dá)到 maxmemory 配置時(shí)候,也會(huì)觸發(fā) Key 的刪除操作奔坟。
———————————————————————————————————
總結(jié)
如果 Redis 中每天過期大量 Key(比如幾千萬)携栋,那么必須得考慮過期 Key 的清理:
增加 Redis 主動(dòng)清理的頻率(通過調(diào)大hz參數(shù));
手動(dòng)清理過期 Key咳秉,最簡單的方法是進(jìn)行 scan 操作婉支,scan 操作會(huì)觸發(fā)第一種被動(dòng)刪除,scan 操作時(shí)候別忘了加 count澜建;
dbsize 命令返回的 Key 數(shù)量向挖,包含了過期 Key;
randomkey 命令返回的 Key炕舵,不包含過期 Key何之;
scan 命令返回的 Key,包含過期 Key咽筋;
info 命令返回的# Keyspace:
db6:keys=1034937352,expires=994731489,avg_ttl=507838502
keys 對應(yīng)的 Key 數(shù)量等同于 dbsize溶推;(因?yàn)?Redis的特性單線程慷丽, keys 指令會(huì)導(dǎo)致線程阻塞一段時(shí)間窃蹋,線上服務(wù)會(huì)停頓,直到指令執(zhí)行完畢身冀,服務(wù)才能恢復(fù)睹耐。這個(gè)時(shí)候可以使用 scan 指令舰褪,scan 指令可以無阻塞的提取出指定模式的key 列表,但是會(huì)有一定的重復(fù)概率疏橄,在客戶端做一次去重就可以了占拍,但是整體所花費(fèi)的時(shí)間會(huì)比直接用 keys 指令長略就。)
expires 指的是設(shè)置了過期時(shí)間的 Key 數(shù)量;
avg_ttl 指設(shè)置了過期時(shí)間的 Key 的平均過期時(shí)間(單位:毫秒)晃酒;
———————————————————————————————————
最后再附上一些參考文章:
http://lxw1234.com/archives/2017/07/874.htm