Redis中鍵過期功能的實現(xiàn)

前言

最近在需求開發(fā)中又用到了我們熟知的Redis字符串操作SET命令偷崩,可以設置指定key的值value及該key的生存時間(Time To Live,TTL)腐宋。相關命令的語法如下:

set key value [EX seconds] [PX milliseconds] [NX|XX]    //TTL由EX指定秒或PX指定毫秒

expire key seconds  //expire指定TTL养交,單位為秒
pexpire key milliseconds    //pexpire指定TTL枚抵,單位為毫秒

expireat key timestamp  //expireat指定過期時間戳,單位為秒
pexpireat key milliseconds-timestamp    //pexpireat指定過期時間戳造烁,單位為毫秒

TTL key //key的剩余生存時間否过,單位是秒
PTTL key //key的剩余生存時間,單位是毫秒

PERSIST key //移除key的過期時間

這些命令用起來挺熟練惭蟋,可轉(zhuǎn)念一想苗桂,Redis中鍵的自動過期是如何實現(xiàn)的呢?在翻閱資料及源碼的基礎上告组,本文主要從過期時間處理煤伟、自動刪除過期鍵策略等方面簡要介紹該功能的實現(xiàn)。

鍵的過期時間處理

設置過期時間

前言中提到木缝,Redis有四個不同命令可以用于設置鍵的生存時間或過期時間便锨。

可以通過EXPIRE或PEXPIRE命令設置該key的生存時間(Time To Live,TTL)我碟,在經(jīng)過指定秒或毫秒后放案,Redis服務器就會自動刪除生存時間為0的鍵key。

同時可以使用EXPIREAT或PEXPIREAT命令給鍵key設置過期時間(expire time)矫俺。

雖然命令形式多樣卿叽,但實際上EXPIRE、PEXPIRE恳守、EXPIREAT三個命令都是使用PEXPIREAT命令來實現(xiàn)的考婴,轉(zhuǎn)換方法很簡單,就是將過期時間換算成時間戳催烘,并保持時間單位統(tǒng)一沥阱。

保存過期時間

redisDb結(jié)構(gòu)的expires字典保存了數(shù)據(jù)庫中所有鍵的過期時間,被稱為“過期字典”伊群。

  • 過期字典是一個指針考杉,指向鍵空間中的某個對象(也即時某個數(shù)據(jù)庫鍵)。
  • 過期字典的值是一個long long類型的整數(shù)舰始,保存了鍵所指向的數(shù)據(jù)庫鍵的過期時間(一個毫秒精度的UNIX時間戳)崇棠。
移除過期時間

PERSIST命令可以移除一個鍵的過期時間,實際就是PEXPIREAT命令的反操作:PERSIST命令在過期字典中查找給定的鍵丸卷,并解除鍵和值(過期時間)在過期字典中的關聯(lián)枕稀。

計算并返回剩余生存時間

可以使用TTL或PTTL命令查找給定鍵key的剩余生存時間(key距離被服務器刪除還剩多少秒/毫秒),兩個命令都是通過計算鍵的過期時間和當前時間的差值實現(xiàn)的。

過期鍵的判定

Redis通過查詢過期字典的方式檢查一個給定鍵是否過期:

  1. 檢查給定鍵是否存在于過期字典:如果存在萎坷,那么取得鍵的過期時間凹联;
  2. 檢查當前UNIX時間戳是否大于鍵的過期時間:如果是的話,name鍵已過期哆档;否則鍵未過期蔽挠。

過期鍵刪除策略

常見的三種刪除策略對比
刪除策略 實現(xiàn) 優(yōu)點 缺點
定時刪除 設置鍵的過期時間的同時,創(chuàng)建一個定時器(Timer)瓜浸,讓定時器在鍵的過期時間來臨時澳淑,立即執(zhí)行對鍵的刪除操作。 內(nèi)存占用率低插佛,通過使用定時器杠巡,可以保證過期鍵會盡可能快地被刪除,并釋放過期鍵所占的內(nèi)存朗涩。 占用較多cpu時間忽孽,影響服務器的響應時間和吞吐量。
惰性刪除 放任鍵過期不管谢床,但是每次獲取鍵時兄一,都檢查鍵是否已過期,如果過期則刪除該鍵识腿;否則返回該鍵出革。 cpu占用率低,只會在取出鍵時才進行過期檢查渡讼,可以保證刪除的目標僅限于當前的鍵骂束,不會在其它過期鍵上花費任何cpu時間。 浪費內(nèi)存成箫,有內(nèi)存泄漏的風險展箱。
定期刪除 每隔一段時間就對數(shù)據(jù)庫做一次過期鍵的刪除。但每次要刪除多少過期鍵蹬昌、要檢查多少個db混驰,則由算法決定。 是前兩種策略的整合和折中皂贩,減少了內(nèi)存和cpu的無謂占用栖榨。 難以確定刪除操作執(zhí)行的時長和頻率。

Redis的過期鍵刪除策略

Redis服務器實際使用的是惰性刪除和定期刪除兩種策略:通過配合使用這兩種策略明刷,服務器可以很好地在合理使用cpu和避免浪費內(nèi)存空間之間取得平衡婴栽。

惰性刪除策略的實現(xiàn)

過期鍵的惰性刪除策略由db.c/expireIfNeeded函數(shù)實現(xiàn),所有讀寫數(shù)據(jù)庫的Redis命令在執(zhí)行之前都會調(diào)用expireIfNeeded函數(shù)對輸入鍵進行檢查:

  • 如果輸入鍵已經(jīng)過期辈末,那么expireIfNeeded函數(shù)將輸入鍵從數(shù)據(jù)庫中刪除愚争。
  • 如果輸入鍵未過期映皆,那么expireIfNeeded函數(shù)不做動作。

expireIfNeeded函數(shù)就像一個過濾器准脂,它可以在命令真正執(zhí)行之前劫扒,過濾掉過期的輸入鍵檬洞,從而避免命令接觸到過期鍵狸膏。另外,因為每個被訪問的鍵都可能因為過期而被expireIfNeeded函數(shù)刪除添怔,所以每個命令的實現(xiàn)函數(shù)都必須能同時處理鍵存在和不存在的情況:

  • 當鍵存在時湾戳,命令按照鍵存在的情況執(zhí)行。
  • 當鍵不存在或者鍵因為過期而被expireIfNeeded函數(shù)刪除時广料,命令按照鍵不存在的情況執(zhí)行砾脑。
定期刪除策略的實現(xiàn)

過期鍵的定期刪除策略由redis.c/activeExpireCycle函數(shù)實現(xiàn),每當Redis的服務器周期性操作redis.c/serverCron函數(shù)執(zhí)行時艾杏,activeExpireCycle函數(shù)就會被調(diào)用韧衣,它在規(guī)定的時間內(nèi),分多次遍歷服務器中的各個數(shù)據(jù)庫购桑,從數(shù)據(jù)庫的expires字典中隨機檢查一部分鍵的過期時間畅铭,并刪除其中的過期鍵。

activeExpireCycle函數(shù)的工作模式可以總結(jié)如下:

  • 函數(shù)每次運行時勃蜘,都從一定數(shù)量的數(shù)據(jù)庫(取min(默認16硕噩,實際數(shù)量))中取出一定數(shù)量的隨機鍵(默認20)進行檢查,并刪除其中的過期鍵缭贡。
  • 全局變量current_db會記錄當前activeExpireCycle函數(shù)檢查的進度炉擅,并在下一次activeExpireCycle函數(shù)調(diào)用時,接著上一次的進度進行處理阳惹。
  • 隨著activeExpireCycle函數(shù)的不斷執(zhí)行谍失,服務器中的所有db都會被檢查一遍,這時函數(shù)將current_db變量重置為0莹汤,然后進行新一輪的定期刪除快鱼。

小結(jié)

本文對Redis中鍵過期功能的實現(xiàn)做了一個簡要介紹,相信讀者看完之后會對大致的實現(xiàn)方案有所了解体啰,但更多細節(jié)推薦閱讀《Redis涉及與實現(xiàn)》攒巍,當然想自己去研究源碼更好啦。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荒勇,一起剝皮案震驚了整個濱河市柒莉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沽翔,老刑警劉巖兢孝,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窿凤,死亡現(xiàn)場離奇詭異,居然都是意外死亡跨蟹,警方通過查閱死者的電腦和手機雳殊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窗轩,“玉大人夯秃,你說我怎么就攤上這事×∫眨” “怎么了仓洼?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長堤舒。 經(jīng)常有香客問我色建,道長,這世上最難降的妖魔是什么舌缤? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任箕戳,我火速辦了婚禮,結(jié)果婚禮上国撵,老公的妹妹穿的比我還像新娘陵吸。我一直安慰自己,他們只是感情好卸留,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布走越。 她就那樣靜靜地躺著,像睡著了一般耻瑟。 火紅的嫁衣襯著肌膚如雪旨指。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天喳整,我揣著相機與錄音谆构,去河邊找鬼。 笑死框都,一個胖子當著我的面吹牛搬素,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播魏保,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼熬尺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谓罗?” 一聲冷哼從身側(cè)響起粱哼,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎檩咱,沒想到半個月后揭措,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胯舷,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年绊含,在試婚紗的時候發(fā)現(xiàn)自己被綠了桑嘶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡躬充,死狀恐怖逃顶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情麻裳,我是刑警寧澤口蝠,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布器钟,位于F島的核電站津坑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏傲霸。R本人自食惡果不足惜疆瑰,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昙啄。 院中可真熱鬧穆役,春花似錦、人聲如沸梳凛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽韧拒。三九已至淹接,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叛溢,已是汗流浹背塑悼。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留楷掉,地道東北人厢蒜。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像烹植,于是被迫代替她去往敵國和親斑鸦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 1.Redis特性 1)速度快:數(shù)據(jù)存放在內(nèi)存上草雕、基于C語言實現(xiàn)巷屿、單線程架構(gòu)預防多線程競爭問題;2)基于鍵值對的數(shù)...
    Sponge1128閱讀 616評論 0 1
  • 制定Redis過期策略促绵,是整個Redis緩存策略的關鍵之一攒庵,因為內(nèi)存來說嘴纺,公司不可能無限大,所以就要對key進行一...
    JackFrost_fuzhu閱讀 4,832評論 1 10
  • 9.1 服務器中的數(shù)據(jù)庫 Redis服務器將所有的數(shù)據(jù)庫都保存在服務器狀態(tài)redis.h/redisServer結(jié)...
    豬大金閱讀 366評論 0 0
  • 這節(jié)課告訴我浓冒,想要內(nèi)心愉快的堅持下去栽渴,想明白很重要,才能真正的學以致用稳懒,也能做好家人的榜樣闲擦,尤其是孩子的榜樣。 學...
    平和生活閱讀 519評論 0 1
  • 面具外 你微笑著 誰也不知道 你的失落 面具內(nèi) 你傷心著 誰也不知道 你的痛苦 你不露聲色 怕被看穿 你無動于衷 ...
    Keya的意識空間閱讀 256評論 5 5