如何理解redis數(shù)據(jù)庫、鍵過期的實現(xiàn),相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
創(chuàng)新互聯(lián)建站2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站設(shè)計、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元那曲做網(wǎng)站,已為上家服務(wù),為那曲各地企業(yè)和個人服務(wù),聯(lián)系電話:18980820575
我們先看代碼 server.h/redisServer
struct redisServer{
...
//保存 db 的數(shù)組
redisDb *db;
//db 的數(shù)量
int dbnum;
...
}
再看redisDb的代碼:
typedef struct redisDb {
dict *dict; /* The keyspace for this DB */
dict *expires; /* Timeout of keys with a timeout set */
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP)*/
dict *ready_keys; /* Blocked keys that received a PUSH */
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
int id; /* Database ID */
long long avg_ttl; /* Average TTL, just for stats */
} redisDb;
總體來說redis的 server 包含若干個(默認(rèn)16個) redisDb 數(shù)據(jù)庫。
Redis 是一個 k-v 存儲的鍵值對數(shù)據(jù)庫。其中字典 dict 保存了數(shù)據(jù)庫中的所有鍵值對,這個地方叫做 keyspace
直譯過來就是“鍵空間”。
所以我們就可以這么認(rèn)為,在 redisDb 中我們使用 dict(字典)來維護鍵空間。
keyspace 的 kay 是數(shù)據(jù)庫的 key,每一個key 是一個字符串對象。注意不是字符串,而是字符串對象。
keyspace 的 value 是數(shù)據(jù)庫的 value,這個 value 可以是 redis 的,字符串對象,列表對象,哈希表對象,集合對象或者有序?qū)ο笾械囊环N。
所以對于數(shù)據(jù)的增刪改查,就是對 keyspace 這個大 map 的增刪改查。
當(dāng)我們執(zhí)行:
>redis SET mobile "13800000000"
實際上就是為 keyspace 增加了一個 key 是包含字符串“mobile”的字符串對象,value 為包含字符“13800000000”的字符串對象。
看圖:
對于刪改查,沒啥好說的。類似java 的 map 操作,大多數(shù)程序員應(yīng)該都能理解。
需要特別注意的是,再執(zhí)行對鍵的讀寫操作的時候,Redis 還要做一些額外的維護動作:
維護 hit 和 miss 兩個計數(shù)器。用于統(tǒng)計 Redis 的緩存命中率。
更新鍵的 LRU 時間,記錄鍵的最后活躍時間。
如果在讀取的時候發(fā)現(xiàn)鍵已經(jīng)過期,Redis 先刪除這個過期的鍵然后再執(zhí)行余下操作。
如果有客戶對這個鍵執(zhí)行了 WATCH 操作,會把這個鍵標(biāo)記為 dirty,讓事務(wù)注意到這個鍵已經(jīng)被改過。
沒修改一次 dirty 會增加1。
如果服務(wù)器開啟了數(shù)據(jù)庫通知功能,鍵被修改之后,會按照配置發(fā)送通知。
Redis 作為緩存使用最主要的一個特性就是可以為鍵值對設(shè)置過期時間。就看看 Redis 是如果實現(xiàn)這一個最重要的特性的?
在 Redis 中與過期時間有關(guān)的命令
EXPIRE 設(shè)置 key 的存活時間單位秒
EXPIREAT 設(shè)置 key 的過期時間點單位秒
PEXPIRE 設(shè)置 key 的存活時間單位毫秒
PEXPIREAT 設(shè)置 key 的過期時間點單位毫秒
其實這些命令,底層的命令都是由 REXPIREAT 實現(xiàn)的。
在 redisDb 中使用了 dict *expires,來存儲過期時間的。其中 key 指向了 keyspace 中的 key(c 語言中的指針), value 是一個 long long 類型的時間戳,標(biāo)定這個 key 過期的時間點,單位是毫秒。
如果我們?yōu)樯衔牡?mobile 增加一個過期時間。
>redis PEXPIREAT mobile 1521469812000
這個時候就會在過期的 字典中增加一個鍵值對。如下圖:
對于過期的判斷邏輯就很簡單:
在 字典 expires 中 key 是否存在。
如果 key 存在,value 的時間戳是否小于當(dāng)前系統(tǒng)時間戳。
接下來就需要討論一下過期的鍵的刪除策略。
key的刪除有三種策略:
定時刪除,Redis定時的刪除內(nèi)存里面所有過期的鍵值對,這樣能夠保證內(nèi)存友好,過期的key都會被刪除,但是如果key的數(shù)量很多,一次刪除需要CPU運算,CPU不友好。
惰性刪除,只有 key 在被調(diào)用的時候才去檢查鍵值對是否過期,但是會造成內(nèi)存中存儲大量的過期鍵值對,內(nèi)存不友好,但是極大的減輕CPU 的負(fù)擔(dān)。
定時部分刪除,Redis定時掃描過期鍵,但是只刪除部分,至于刪除多少鍵,根據(jù)當(dāng)前 Redis 的狀態(tài)決定。
這三種策略就是對時間和空間有不同的傾向。Redis為了平衡時間和空間,采用了后兩種策略 惰性刪除和定時部分刪除。
惰性刪除比較簡單,不做過多介紹。主要討論一下定時部分刪除。
過期鍵的定時刪除的策略由 expire.c/activeExpireCycle() 函數(shù)實現(xiàn),server.c/serverCron() 定時的調(diào)用 activieExpireCycle()
。
activeExpireCycle 的大的操作原則是,如果過期的key比較少,則刪除key的數(shù)量也比較保守,如果,過期的鍵多,刪除key的策略就會很激進(jìn)。
static unsigned int current_db = 0; /* Last DB tested. */
static int timelimit_exit = 0; /* Time limit hit in previous call? */
static long long last_fast_cycle = 0; /* When last fast cycle ran. */
首先三個 static
全局參數(shù)分別記錄目前遍歷的 db下標(biāo),上一次刪除是否是超時退出的,上一次快速操作是什么時候進(jìn)行的。
計算 timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;
可以理解為 25% 的 cpu 時間。
如果 db 中 expire 的大小為0 不操作
expire 占總 key 小于 1% 不操作
num = dictSize(db->expires);num 是 expire 使用的key的數(shù)量。
slots = dictSlots(db->expires); slots 是 expire 字典的尺寸大小。
已使用的key(num) 大于 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 則設(shè)置為 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP。也就是說每次只檢查 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 個鍵。
隨機獲取帶過期的 key。計算是否過期,如果過期就刪除。
然后各種統(tǒng)計,包括刪除鍵的次數(shù),平均過期時間。
每遍歷十六次,計算操作時間,如果超過 timelimit 結(jié)束返回。
如果刪除的過期鍵大于 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 的 1\4 就跳出循環(huán),結(jié)束。
步驟比較復(fù)雜,總結(jié)一下:(這里都是以默認(rèn)配置描述)
redis 會用最多 25% 的 cpu 時間處理鍵的過期。
遍歷所有的 redisDb
在每個 redisDb 中如果數(shù)據(jù)中沒有過期鍵或者過期鍵比例過低就直接進(jìn)入下一個 redisDb。
否則,遍歷 redisDb 中的過期鍵,如果刪除的鍵達(dá)到有過期時間的的key 的25% ,或者操作時間大于 cpu 時間的 25% 就結(jié)束當(dāng)前循環(huán),進(jìn)入下一個redisDb。
看完上述內(nèi)容,你們掌握如何理解Redis數(shù)據(jù)庫、鍵過期的實現(xiàn)的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
當(dāng)前名稱:如何理解Redis數(shù)據(jù)庫、鍵過期的實現(xiàn)
本文路徑:http://www.rwnh.cn/article2/gpoeoc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、標(biāo)簽優(yōu)化、域名注冊、虛擬主機、ChatGPT、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)