Redis Key過(guò)期策略詳解
概述
Redis的Key過(guò)期策略是其內(nèi)存管理系統(tǒng)的核心組成部分,主要包括「被動(dòng)過(guò)期」、「主動(dòng)過(guò)期」和「內(nèi)存淘汰」三個(gè)機(jī)制。
本文將著重講解Redis的Key過(guò)期策略,從實(shí)現(xiàn)原理、工作流程到最佳實(shí)踐進(jìn)行全面解析。
Redis Key過(guò)期策略
Redis采用多策略組合的方式管理Key過(guò)期,主要包括三種機(jī)制:定時(shí)刪除、惰性刪除和定期刪除。
下面將分別對(duì)這三種key過(guò)期機(jī)制進(jìn)行實(shí)現(xiàn)原理、優(yōu)缺點(diǎn)、Redis采用的策略、以及RDB/AOF對(duì)不同過(guò)期策略的處理上的講解。
定時(shí)刪除
實(shí)現(xiàn)原理:
- 在設(shè)置key的過(guò)期時(shí)間的同時(shí),為該key創(chuàng)建一個(gè)定時(shí)器,讓定時(shí)器在key過(guò)期時(shí)間來(lái)臨時(shí),對(duì)key進(jìn)行刪除。
優(yōu)點(diǎn):
- 內(nèi)存友好,可以及時(shí)清除過(guò)期的數(shù)據(jù)
缺點(diǎn):
- cpu不友好,會(huì)占用大量cpu資源去處理過(guò)期的數(shù)據(jù),從而影響緩存的響應(yīng)時(shí)間和吞吐量。
- 定時(shí)器的創(chuàng)建耗時(shí),若為每一個(gè)設(shè)置過(guò)期時(shí)間key創(chuàng)建一個(gè)定時(shí)器(將會(huì)產(chǎn)生大量的定時(shí)器),性能影響嚴(yán)重。
- Redis未采用此策略。
惰性刪除
實(shí)現(xiàn)原理:
- 只有當(dāng)訪(fǎng)問(wèn)key時(shí),才會(huì)判斷該key是否已經(jīng)是過(guò)期(觸發(fā)expireIfNeeded()檢查),過(guò)期則清除。
優(yōu)點(diǎn):
- cpu友好,零額外開(kāi)銷(xiāo)
- 刪除操作精準(zhǔn)
缺點(diǎn):
- 內(nèi)存泄漏風(fēng)險(xiǎn):不訪(fǎng)問(wèn)的過(guò)期Key永遠(yuǎn)存在。
- 極端情況下可能會(huì)出現(xiàn)大量過(guò)期key沒(méi)有再被訪(fǎng)問(wèn),從而不會(huì)被刪除,占用大量無(wú)效內(nèi)存。
定期刪除
實(shí)現(xiàn)原理:
每隔一定時(shí)間,掃描一定數(shù)量在數(shù)據(jù)庫(kù)中expires字典(過(guò)期字典)中一定數(shù)量的key,并清除其中已過(guò)期的key。
工作機(jī)制
- 周期性執(zhí)行activeExpireCycle()
- 隨機(jī)抽取部分過(guò)期字典中的Key檢查
- 采用自適應(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%: # 過(guò)期率<25%則退出
break優(yōu)點(diǎn):
- 該策略是前兩者的一個(gè)折中方案,通過(guò)調(diào)整定時(shí)掃描的時(shí)間間隔和每次掃描的限定耗時(shí),可以在不同情況下使得cpu和內(nèi)存資源達(dá)到最優(yōu)的平衡效果。
- 通過(guò)限制刪除的時(shí)長(zhǎng)和頻率,來(lái)減少刪除操作對(duì)cpu時(shí)間的占用 — 解決「定時(shí)刪除」的缺點(diǎn)
- 定期刪除過(guò)期key — 解決「惰性刪除」的缺點(diǎn)
缺點(diǎn):
- 在內(nèi)存友好方面,不如「定時(shí)刪除」。
- 在cpu時(shí)間友好方面,不如「惰性刪除」。
難點(diǎn):
- 合理設(shè)置操作的執(zhí)行時(shí)長(zhǎng)(每次刪除執(zhí)行多長(zhǎng)時(shí)間)和執(zhí)行頻率(每隔多久時(shí)間做一次刪除),這個(gè)需要各個(gè)業(yè)務(wù)場(chǎng)景根據(jù)實(shí)際情況進(jìn)行動(dòng)態(tài)調(diào)整。
Redis采用的策略
Redis采用**「惰性刪除」** + **「定期刪除」**的混合策略
- 混合策略架構(gòu)

「惰性刪除」 + 「定期刪除」策略
惰性刪除流程
- 在進(jìn)行g(shù)et或setnx等操作時(shí),先檢查key是否過(guò)期。
- 若過(guò)期,則刪除key,然后執(zhí)行相應(yīng)操作。
- 若沒(méi)過(guò)期,則直接執(zhí)行相應(yīng)操作。
定期刪除流程
1.遍歷每個(gè)數(shù)據(jù)庫(kù)(即redis.conf中配置的“database”數(shù)量,默認(rèn)為16)。
2.檢查當(dāng)前庫(kù)中指定個(gè)數(shù)key(默認(rèn)是每個(gè)庫(kù)檢查20個(gè)key,相當(dāng)于循環(huán)執(zhí)行20次)。
- a. 如果當(dāng)前庫(kù)中沒(méi)有一個(gè)key設(shè)置了過(guò)期時(shí)間,直接執(zhí)行下一個(gè)庫(kù)的遍歷。
- b. 隨機(jī)獲取一個(gè)設(shè)置了過(guò)期時(shí)間的key,檢查key是否過(guò)期,如過(guò)期,刪除key。
- c. 判斷定期刪除操作是否已經(jīng)達(dá)到指定時(shí)長(zhǎng),若達(dá)到,則退出定期刪除。
注意事項(xiàng)
- 定期刪除,在程序中有一個(gè)全局變量current_db來(lái)記錄下一個(gè)將要便利的庫(kù)。
- 假設(shè)有16個(gè)庫(kù),這一次定期刪除遍歷了10個(gè),那此時(shí)的current_db就是11,下一次定期刪除就從第 11庫(kù)開(kāi)始遍歷。
持久化對(duì)過(guò)期策略的處理
RDB對(duì)過(guò)期策略的處理
說(shuō)明:過(guò)期key對(duì)RDB沒(méi)有影響
原理:
1.從內(nèi)存持久化數(shù)據(jù)到RDB文件
主節(jié)點(diǎn)
- a. 生成RDB快照時(shí)會(huì)主動(dòng)過(guò)濾已過(guò)期的Key。
- b. 僅持久化未過(guò)期的Key-value對(duì)。
從節(jié)點(diǎn)
- a. 即使接收到的RDB文件包含未實(shí)際過(guò)期的Key。
- b. 加載時(shí)仍會(huì)執(zhí)行過(guò)期檢查(雙重保障)。
關(guān)鍵源碼
// rdb.c 源碼關(guān)鍵邏輯
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime) {
if (expiretime != -1 && expiretime < mstime()) {
return 0; // 跳過(guò)已過(guò)期的Key
}
// 保存未過(guò)期的Key...
}2.從RDB文件恢復(fù)數(shù)據(jù)到內(nèi)存
全量加載流程:
- a. 清空當(dāng)前數(shù)據(jù)庫(kù)
- b. 解析RDB文件內(nèi)容
- c. 對(duì)每個(gè)Key執(zhí)行expireIfNeeded()檢查
- c. 僅加載未過(guò)期的Key
AOF對(duì)過(guò)期策略的處理
說(shuō)明:過(guò)期key對(duì)AOF沒(méi)有影響
原理:
1.從內(nèi)存持久化數(shù)據(jù)到AOF文件
正常AOF追加模式
- a. AOF會(huì)將對(duì)應(yīng)Key的操作一并寫(xiě)入文件中
| 操作類(lèi)型 | AOF記錄內(nèi)容 |
|---|---|
| Key設(shè)置過(guò)期 | PEXPIREAT key timestamp |
| Key自然過(guò)期 | DEL key(實(shí)際由propagateExpire()生成) |
| 手動(dòng)刪除 | 直接記錄DEL key |
AOF重寫(xiě)時(shí)
- a. 重寫(xiě)時(shí),會(huì)先判斷Key是否過(guò)期,已過(guò)期的Key不會(huì)重寫(xiě)到AOF文件
與RDB的區(qū)別
- a. 仍會(huì)記錄Key的過(guò)期時(shí)間(PEXPIREAT)
- b. 但實(shí)際數(shù)據(jù)只有未過(guò)期Key會(huì)被寫(xiě)入
復(fù)制場(chǎng)景下的特殊處理
主從復(fù)制流程
| 節(jié)點(diǎn)角色 | 過(guò)期Key處理方式 |
|---|---|
| 主節(jié)點(diǎn) | 惰性刪除+定期刪除 |
| 從節(jié)點(diǎn) | 僅依賴(lài)主節(jié)點(diǎn)的DEL同步 |
關(guān)鍵機(jī)制:
- a. 主節(jié)點(diǎn)過(guò)期后會(huì)向從節(jié)點(diǎn)傳播DEL命令
- b. 從節(jié)點(diǎn)不會(huì)主動(dòng)刪除Key(即使已過(guò)期)
- c. 3.2+版本引入replica-ignore-expire配置(默認(rèn)關(guān)閉)
數(shù)據(jù)一致性風(fēng)險(xiǎn)
場(chǎng)景:
- Key在主節(jié)點(diǎn)過(guò)期但尚未同步到從節(jié)點(diǎn)
- 此時(shí)主節(jié)點(diǎn)宕機(jī),從節(jié)點(diǎn)晉升后:
- RDB加載:會(huì)重新檢查過(guò)期
- AOF回放:依賴(lài)記錄的DEL命令
總結(jié)對(duì)比表
| 持久化方式 | 生成時(shí)處理 | 加載時(shí)處理 | 復(fù)制傳播 |
|---|---|---|---|
| RDB | 過(guò)濾過(guò)期Key | 二次檢查 | 全量同步 |
| AOF | 記錄DEL命令 | 按序重放 | 增量同步 |
| 混合模式 | RDB部分過(guò)濾 | 組合加載 | 混合同步 |
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Redis中的數(shù)據(jù)結(jié)構(gòu)跳表詳解
跳表是一種基于并聯(lián)的鏈表結(jié)構(gòu),用于在有序元素序列中快速查找元素的數(shù)據(jù)結(jié)構(gòu),本文給大家介紹Redis中的數(shù)據(jù)結(jié)構(gòu)跳表,感興趣的朋友跟隨小編一起看看吧2024-06-06
關(guān)于在Redis中使用Pipelining加速查詢(xún)的問(wèn)題
這篇文章主要介紹了在Redis中使用Pipelining加速查詢(xún),Redis是一個(gè)client-server模式的TCP服務(wù),也被稱(chēng)為Request/Response協(xié)議的實(shí)現(xiàn),本文通過(guò)一個(gè)例子給大家詳細(xì)介紹,感興趣的朋友一起看看吧2022-05-05
Redis優(yōu)化token校驗(yàn)主動(dòng)失效的實(shí)現(xiàn)方案
在普通的token頒發(fā)和校驗(yàn)中 當(dāng)用戶(hù)發(fā)現(xiàn)自己賬號(hào)和密碼被暴露了時(shí)修改了登錄密碼后舊的token仍然可以通過(guò)系統(tǒng)校驗(yàn)直至token到達(dá)失效時(shí)間,所以系統(tǒng)需要token主動(dòng)失效的一種能力,所以本文給大家介紹了Redis優(yōu)化token校驗(yàn)主動(dòng)失效的實(shí)現(xiàn)方案,需要的朋友可以參考下2024-03-03
redis實(shí)現(xiàn)延時(shí)隊(duì)列的兩種方式(小結(jié))
這篇文章主要介紹了redis實(shí)現(xiàn)延時(shí)隊(duì)列的兩種方式(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
淺析Redis中紅鎖RedLock的實(shí)現(xiàn)原理
RedLock?是一種分布式鎖的實(shí)現(xiàn)算法,由?Redis?的作者?Salvatore?Sanfilippo(也稱(chēng)為?Antirez)提出,本文主要為大家詳細(xì)介紹了紅鎖RedLock的實(shí)現(xiàn)原理,感興趣的可以了解下2024-02-02
Redisson如何解決Redis分布式鎖提前釋放問(wèn)題
本文主要介紹了Redisson如何解決Redis分布式鎖提前釋放問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

