前言
前面咱們介紹了Redis的五種數據結構,這一篇咱們換一個角度,讓咱們來看看Redis服務器的數據庫。單個Redis服務器默認會建立16個數據庫,數據庫之間的數據是相互隔離的。默認的話使用的是0庫。redis
數據庫
Redis服務器將全部數據庫都保存在服務器狀態 redis.h/redisServer結構的db數組中,db數組的每一個項都是一個redis.h/redisDb結構,每一個redisDb結構表明一個數據庫。在初始化服務器時,程序會根據服務器狀態的dbnum屬性來決定應該建立多少個數據庫,默認的話是16個。數據庫
struct redisServer{ ..... //一個數組,保存着服務器中的全部數據庫 redisDb *db; //服務器的數據庫數量 int dbnum; .... }
服務器數據庫的示例圖以下:
鍵空間
Redis是一個鍵值對(key-value pair)數據庫服務器,服務器中的每一個數據庫都由一個redis.h/redisDb結構表示,其中,redisDb結構的dict字典保存了數據庫中的全部鍵值對,咱們將這個字典稱爲鍵空間(key space)。數據結構以下:數組
typedef struct redisDb{ ..... //數據庫鍵空間,保存着數據庫中的全部鍵值對 dict *dict ..... }
須要說明的是:服務器
- 鍵空間和用戶所見的數據庫是直接對應的,也就是說當前客戶端鏈接的是哪一個數據庫,鍵空間就是哪一個數據庫的鍵空間。
- 鍵空間的鍵也就是數據庫的鍵,每一個鍵都是一個字符串對象。這個能夠這樣理解,就是說數據庫中的數據都是存在鍵空間的。
- 鍵空間的值也就是數據庫中的值,每一個值能夠是字符串對象、列表對象、哈希表對象、集合對象和有序集合對象中的任意一種Redis對象。
下面咱們對一個空的數據庫進行設值操做,咱們分別設值了一個字符串對象message,一個列表對象order,一個哈希對象book。
127.0.0.1:6379> set message "hello world" OK 127.0.0.1:6379> lpush order "111" "222" "333" (integer) 3 127.0.0.1:6379> HSET book name "Learn Redis" author zhangsan (integer) 2
其鍵空間的存儲狀況下如圖所示:
數據結構
添加新鍵
添加一個新鍵值對到數據庫,實際上就是將一個新鍵值對添加到鍵空間字典裏面,其中鍵爲字符串對象,而值則爲任意一種類型的Redis對象。
以下圖新增一個bookpage的鍵。
spa
HSET bookpage page 123
刪除鍵
刪除數據庫中的一個鍵,實際上就是在鍵空間裏面刪除鍵所對應的鍵值對對象。設計
更新鍵
對一個數據庫鍵進行更新,實際上就是對鍵空間裏面鍵所對應的值對象進行更新,根據值對象的類型不一樣,更新的具體方法有所不一樣。下面以對上面的鍵book爲例,將author的field修改爲lisicode
127.0.0.1:6379> HSET book name "Learn Redis" author lisi (integer) 0 127.0.0.1:6379> hgetall book 1) "name" 2) "Learn Redis" 3) "author" 4) "lisi"
對鍵取值
對一個數據庫鍵進行取值,實際上就是在鍵空間中取出鍵所對應的值對象,根據值對象的類型不一樣,具體的取值方法也有所不一樣。對象
讀寫鍵空間時的維護操做
- 在讀取一個鍵以後(讀操做和寫操做都要對鍵進行讀取),服務器會根據鍵是否存在來更新服務器的鍵空間命中(hit)次數或鍵空間不命中(miss)次數,這兩個值能夠在INFO status命令的keyspace_hits屬性和keyspcace_misses屬性中查看。
- 在讀取一個鍵以後,服務器會更新鍵的LRU(最後一次使用)時間,這個值能夠用於計算鍵的閒置時間,使用
OBJECT idletime <key>
命令能夠查看鍵key的閒置時間。 - 若是服務器在讀取一個鍵時發現該鍵已通過期,那麼服務器會先刪除這個過時鍵,而後才執行餘下的其餘操做。
- 若是有客戶端使用WATCH命令監視了某個鍵,那麼服務器在對監視的鍵進行修改以後,會將這個鍵標記爲髒(dirty),從而讓事務程序注意到這個鍵已經被修改過 。
總結
本文主要是參考《Redis的設計與實現第二版》寫的一篇關於Redis的數據庫以及數據庫鍵空間的文章。單機的Redis服務器默認有16個數據庫,對數據庫的操做本質上就是對鍵空間的操做。blog
參考
《Redis的設計與實現第二版》