Redis Key過期策略

概述

?Redis的Key過期策略是其內(nèi)存管理系統(tǒng)的核心組成部分,主要包括「被動(dòng)過期」、「主動(dòng)過期」和「內(nèi)存淘汰」三個(gè)機(jī)制。其中「內(nèi)存淘汰」相關(guān)內(nèi)容已經(jīng)在上一篇「Redis內(nèi)存淘汰策略」中進(jìn)行了詳細(xì)的講解,有信興趣的同學(xué)可以在回顧上一篇文章。本文將著重講解Redis的Key過期策略,從實(shí)現(xiàn)原理、工作流程到最佳實(shí)踐進(jìn)行全面解析。


Redis Key過期策略

?Redis采用多策略組合的方式管理Key過期,主要包括三種機(jī)制:定時(shí)刪除、惰性刪除定期刪除。
?下面將分別對這三種key過期機(jī)制進(jìn)行實(shí)現(xiàn)原理、優(yōu)缺點(diǎn)、Redis采用的策略、以及RDB/AOF對不同過期策略的處理上的講解。

定時(shí)刪除

?實(shí)現(xiàn)原理
??在設(shè)置key的過期時(shí)間的同時(shí),為該key創(chuàng)建一個(gè)定時(shí)器,讓定時(shí)器在key過期時(shí)間來臨時(shí),對key進(jìn)行刪除。
?優(yōu)點(diǎn)
??1. 內(nèi)存友好,可以及時(shí)清除過期的數(shù)據(jù)
?缺點(diǎn)
??1. cpu不友好,會占用大量cpu資源去處理過期的數(shù)據(jù),從而影響緩存的響應(yīng)時(shí)間和吞吐量。
??2. 定時(shí)器的創(chuàng)建耗時(shí),若為每一個(gè)設(shè)置過期時(shí)間key創(chuàng)建一個(gè)定時(shí)器(將會產(chǎn)生大量的定時(shí)器),性能影響嚴(yán)重。
??3. Redis未采用此策略。


惰性刪除

?實(shí)現(xiàn)原理
??只有當(dāng)訪問key時(shí),才會判斷該key是否已經(jīng)是過期(觸發(fā)expireIfNeeded()檢查),過期則清除。
?優(yōu)點(diǎn)
??1. cpu友好,零額外開銷
??2. 刪除操作精準(zhǔn)
?缺點(diǎn)
??1.內(nèi)存泄漏風(fēng)險(xiǎn):不訪問的過期Key永遠(yuǎn)存在。極端情況下可能會出現(xiàn)大量過期key沒有再被訪問,從而不會被刪除,占用大量無效內(nèi)存。


定期刪除

?實(shí)現(xiàn)原理
?每隔一定時(shí)間,掃描一定數(shù)量在數(shù)據(jù)庫中expires字典(過期字典)中一定數(shù)量的key,并清除其中已過期的key。

?工作機(jī)制
??1. 周期性執(zhí)行activeExpireCycle()
??2. 隨機(jī)抽取部分過期字典中的Key檢查
??3. 采用自適應(yīng)算法控制CPU消耗

?核心算法

def activeExpireCycle():
   while True:
    # 每次隨機(jī)檢查20個(gè)Key
    for i in range(20):
        key = random.choice(expires_dict)
        if key.expire_time < now:
            delete_key(key)
    # 動(dòng)態(tài)退出條件
    if checked_keys < 20*25%:  # 過期率<25%則退出
        break

?優(yōu)點(diǎn)
??1.該策略是前兩者的一個(gè)折中方案,通過調(diào)整定時(shí)掃描的時(shí)間間隔和每次掃描的限定耗時(shí),可以在不同情況下使得cpu和內(nèi)存資源達(dá)到最優(yōu)的平衡效果。
??2.通過限制刪除的時(shí)長和頻率,來減少刪除操作對cpu時(shí)間的占用 --- 解決「定時(shí)刪除」的缺點(diǎn)
??3.定期刪除過期key --- 解決「惰性刪除」的缺點(diǎn)

?缺點(diǎn)
??1.在內(nèi)存友好方面,不如「定時(shí)刪除」。
??2.在cpu時(shí)間友好方面,不如「惰性刪除」。

?難點(diǎn)
??1.合理設(shè)置操作的執(zhí)行時(shí)長(每次刪除執(zhí)行多長時(shí)間)和執(zhí)行頻率(每隔多久時(shí)間做一次刪除),這個(gè)需要各個(gè)業(yè)務(wù)場景根據(jù)實(shí)際情況進(jìn)行動(dòng)態(tài)調(diào)整。


Redis采用的策略

?Redis采用「惰性刪除」 + 「定期刪除」的混合策略

?混合策略架構(gòu)

混合策略架構(gòu).png

「惰性刪除」 + 「定期刪除」策略

?惰性刪除流程
??1.在進(jìn)行g(shù)et或setnx等操作時(shí),先檢查key是否過期。
??2.若過期,則刪除key,然后執(zhí)行相應(yīng)操作。
??3.若沒過期,則直接執(zhí)行相應(yīng)操作。

?定期刪除流程
??1.遍歷每個(gè)數(shù)據(jù)庫(即redis.conf中配置的“database”數(shù)量,默認(rèn)為16)。
??2.檢查當(dāng)前庫中指定個(gè)數(shù)key(默認(rèn)是每個(gè)庫檢查20個(gè)key,相當(dāng)于循環(huán)執(zhí)行20次)。
???a. 如果當(dāng)前庫中沒有一個(gè)key設(shè)置了過期時(shí)間,直接執(zhí)行下一個(gè)庫的遍歷。
???b. 隨機(jī)獲取一個(gè)設(shè)置了過期時(shí)間的key,檢查key是否過期,如過期,刪除key。
???c. 判斷定期刪除操作是否已經(jīng)達(dá)到指定時(shí)長,若達(dá)到,則退出定期刪除。
?注意事項(xiàng)
??定期刪除,在程序中有一個(gè)全局變量current_db來記錄下一個(gè)將要便利的庫。假設(shè)有16個(gè)庫,這一次定期刪除遍歷了10個(gè),那此時(shí)的current_db就是11,下一次定期刪除就從第 11庫開始遍歷。


持久化對過期策略的處理

RDB對過期策略的處理

?說明:過期key對RDB沒有影響
?原理
?1.從內(nèi)存持久化數(shù)據(jù)到RDB文件
?主節(jié)點(diǎn)
??a. 生成RDB快照時(shí)會主動(dòng)過濾已過期的Key。
??b. 僅持久化未過期的Key-value對。
?從節(jié)點(diǎn)
??a. 即使接收到的RDB文件包含未實(shí)際過期的Key。
??b. 加載時(shí)仍會執(zhí)行過期檢查(雙重保障)。

?關(guān)鍵源碼

// rdb.c 源碼關(guān)鍵邏輯
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime) {
    if (expiretime != -1 && expiretime < mstime()) {
        return 0; // 跳過已過期的Key
    }
    // 保存未過期的Key...
}

?2.從RDB文件恢復(fù)數(shù)據(jù)到內(nèi)存
?全量加載流程:
??a. 清空當(dāng)前數(shù)據(jù)庫
??b. 解析RDB文件內(nèi)容
??c. 對每個(gè)Key執(zhí)行expireIfNeeded()檢查
??c. 僅加載未過期的Key


AOF對過期策略的處理

?說明:過期key對AOF沒有影響
?原理
?1.從內(nèi)存持久化數(shù)據(jù)到AOF文件

?正常AOF追加模式
??a. AOF會將對應(yīng)Key的操作一并寫入文件中

操作類型 AOF記錄內(nèi)容
Key設(shè)置過期 PEXPIREAT key timestamp
Key自然過期 DEL key(實(shí)際由propagateExpire()生成)
手動(dòng)刪除 直接記錄DEL key

?AOF重寫時(shí)
??a. 重寫時(shí),會先判斷Key是否過期,已過期的Key不會重寫到AOF文件

?與RDB的區(qū)別
??a. 仍會記錄Key的過期時(shí)間(PEXPIREAT)
??b. 但實(shí)際數(shù)據(jù)只有未過期Key會被寫入


復(fù)制場景下的特殊處理

?主從復(fù)制流程

節(jié)點(diǎn)角色 過期Key處理方式
主節(jié)點(diǎn) 惰性刪除+定期刪除
從節(jié)點(diǎn) 僅依賴主節(jié)點(diǎn)的DEL同步

?關(guān)鍵機(jī)制:
??a. 主節(jié)點(diǎn)過期后會向從節(jié)點(diǎn)傳播DEL命令
??b. 從節(jié)點(diǎn)不會主動(dòng)刪除Key(即使已過期)
??c. 3.2+版本引入replica-ignore-expire配置(默認(rèn)關(guān)閉)


數(shù)據(jù)一致性風(fēng)險(xiǎn)

?場景:
??1. Key在主節(jié)點(diǎn)過期但尚未同步到從節(jié)點(diǎn)
??2. 此時(shí)主節(jié)點(diǎn)宕機(jī),從節(jié)點(diǎn)晉升后:
??3. RDB加載:會重新檢查過期
??4. AOF回放:依賴記錄的DEL命令


總結(jié)對比表

持久化方式 生成時(shí)處理 加載時(shí)處理 復(fù)制傳播
RDB 過濾過期Key 二次檢查 全量同步
AOF 記錄DEL命令 按序重放 增量同步
混合模式 RDB部分過濾 組合加載 混合同步
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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