本章將對(duì) Redis 數(shù)據(jù)庫(kù)的構(gòu)造和實(shí)現(xiàn)進(jìn)行討論。
除了說(shuō)明數(shù)據(jù)庫(kù)是如何儲(chǔ)存數(shù)據(jù)對(duì)象之外,本章還會(huì)討論鍵的過(guò)期信息是如何保存,而 Redis 又是如何刪除過(guò)期鍵的。
Redis 中的每個(gè)數(shù)據(jù)庫(kù),都由一個(gè) redis.h/redisDb
結(jié)構(gòu)表示:
typedef struct redisDb {
// 保存著數(shù)據(jù)庫(kù)以整數(shù)表示的號(hào)碼
int id;
// 保存著數(shù)據(jù)庫(kù)中的所有鍵值對(duì)數(shù)據(jù)
// 這個(gè)屬性也被稱(chēng)為鍵空間(key space)
dict *dict;
// 保存著鍵的過(guò)期信息
dict *expires;
// 實(shí)現(xiàn)列表阻塞原語(yǔ),如 BLPOP
// 在列表類(lèi)型一章有詳細(xì)的討論
dict *blocking_keys;
dict *ready_keys;
// 用于實(shí)現(xiàn) WATCH 命令
// 在事務(wù)章節(jié)有詳細(xì)的討論
dict *watched_keys;
} redisDb;
下文將詳細(xì)討論 id
、 dict
和 expires
三個(gè)屬性,以及針對(duì)這三個(gè)屬性所執(zhí)行的數(shù)據(jù)庫(kù)操作。
redisDb
結(jié)構(gòu)的 id
域保存著數(shù)據(jù)庫(kù)的號(hào)碼。
這個(gè)號(hào)碼很容易讓人將它和切換數(shù)據(jù)庫(kù)的 SELECT 命令聯(lián)系在一起,但是,實(shí)際上,id
屬性并不是用來(lái)實(shí)現(xiàn) SELECT 命令,而是給 Redis 內(nèi)部程序使用的。
當(dāng) Redis 服務(wù)器初始化時(shí),它會(huì)創(chuàng)建出 redis.h/REDIS_DEFAULT_DBNUM
個(gè)數(shù)據(jù)庫(kù),并將所有數(shù)據(jù)庫(kù)保存到 redis.h/redisServer.db
數(shù)組中,每個(gè)數(shù)據(jù)庫(kù)的 id
為從 0
到 REDIS_DEFAULT_DBNUM - 1
的值。
當(dāng)執(zhí)行 SELECT number
命令時(shí),程序直接使用 redisServer.db[number]
來(lái)切換數(shù)據(jù)庫(kù)。
但是,一些內(nèi)部程序,比如 AOF 程序、復(fù)制程序和 RDB 程序,需要知道當(dāng)前數(shù)據(jù)庫(kù)的號(hào)碼,如果沒(méi)有 id
域的話,程序就只能在當(dāng)前使用的數(shù)據(jù)庫(kù)的指針,和 redisServer.db
數(shù)組中所有數(shù)據(jù)庫(kù)的指針進(jìn)行對(duì)比,以此來(lái)弄清楚自己正在使用的是那個(gè)數(shù)據(jù)庫(kù)。
以下偽代碼描述了這個(gè)對(duì)比過(guò)程:
def PSEUDO_GET_CURRENT_DB_NUMBER(current_db_pointer):
i = 0
for db_pointer in redisServer.db:
if db_pointer == current_db_pointer:
break
i += 1
return i
有了 id
域的話,程序就可以通過(guò)讀取 id
域來(lái)了解自己正在使用的是哪個(gè)數(shù)據(jù)庫(kù),這樣就不用對(duì)比指針那么麻煩了。
因?yàn)?Redis 是一個(gè)鍵值對(duì)數(shù)據(jù)庫(kù)(key-value pairs database),所以它的數(shù)據(jù)庫(kù)本身也是一個(gè)字典(俗稱(chēng) key space):
在 redisDb
結(jié)構(gòu)的 dict
屬性中,保存著數(shù)據(jù)庫(kù)的所有鍵值對(duì)數(shù)據(jù)。
下圖展示了一個(gè)包含 number
、 book
、 message
三個(gè)鍵的數(shù)據(jù)庫(kù) ——其中 number
鍵是一個(gè)列表,列表中包含三個(gè)整數(shù)值;book
鍵是一個(gè)哈希表,表中包含三個(gè)鍵值對(duì);而 message
鍵則指向另一個(gè)字符串:
更多建議: