Redis支援多個資料庫,並且每個資料庫的資料是隔離的不能共享,並且基於單機才有,如果是叢集就沒有資料庫的概念。
用select命令可以手動切換redis資料庫,預設從0開始
redis> select 0
typedef struct redisDb { //一個redis庫的結構
int id; // 資料庫ID標識
dict *dict; // 鍵空間,存放著所有的鍵值對
dict *expires; // 過期雜湊表,儲存著鍵的過期時間
dict *watched_keys; // 被watch命令監控的key和相應client
long long avg_ttl; // 資料庫內所有鍵的平均TTL(生存時間)
} redisDb;
鍵空間
字典格式(這個字典的底層資料結構就是hash表),鍵是字串物件, 值對應五種不同物件, string物件,list物件,hash物件,集合物件,有序集合對象中任意一種redis物件。
typedef struct redisObject{
//型別
unsigned type:4;
//編碼
unsigned encoding:4;
//指向底層資料結構的指標,一共有6種底層資料結構
void *ptr;
//引用計數
int refcount;
//記錄最後一次被程式訪問的時間
unsigned lru:22;
}robj
1.String物件
Redis 是用 C 語言寫的,但Redis的字串是自己構建了一種名為 簡單動態字串(simple dynamic string,SDS)的抽象型別。
struct sdshdr{
//記錄buf陣列中已使用位元組的數量
//等於 SDS 儲存字串的長度
int len;
//記錄 buf 陣列中未使用位元組的數量
int free;
//位元組陣列,用於儲存字串
char buf[];
}
string物件的編碼型別有 int,raw或者embstr。 int 編碼是用來儲存整數值,raw編碼是用來儲存長字串,而embstr是用來儲存短字串。
2.List物件
底層資料結構是雙向連結串列或者 壓縮列表(ziplist), 當列表儲存元素個數小於512個且每個元素長度小於64位元組時為ziplist, 可以更改list-max-ziplist-value選項和 list-max-ziplist-entries 選項進行配置。 壓縮列表其實就是把資料放在連續的記憶體中。
3.Hash物件
底層資料結構是雜湊表
# hash表
typedef struct dictht{
//雜湊表節點陣列陣列
dictEntry **table;
//雜湊表大小
unsigned long size;
//雜湊表大小掩碼,用於計算索引值
//總是等於 size-1
unsigned long sizemask;
//該雜湊表已有節點的數量
unsigned long used;
}dictht
# hash表節點
typedef struct dictEntry{
//鍵
void *key;
//值
union{
void *val;
uint64_tu64;
int64_ts64;
}v;
//指向下一個具有相同索引值的雜湊表節點,形成連結串列,鏈地址法解決雜湊衝突問題
struct dictEntry *next;
}dictEntry
4.Set物件,集合物件
底層資料結構是整數集合(intset)或者hash表, 當集合物件中所有元素都是整數且所有元素數量不超過512時為intset型別,可通過set-max-intset-entries 進行配置。
typedef struct intset{
//編碼方式
uint32_t encoding;
//集合包含的元素數量
uint32_t length;
//儲存元素的陣列
int8_t contents[];
}intset;
5.zset物件,有序集合
底層資料結構為 跳躍表(skiplist),是一種有序資料結構,它通過在每個節點中維持多個指向其它節點的指標,從而達到快速訪問節點的目的。
Redis使用的記憶體回收演算法是引用計數演算法和LRU演算法
1.引用計數演算法:對於建立的每一個物件都有一個與之關聯的計數器,這個計數器記錄著該物件被使用的次數,垃圾收集器在進行垃圾回收時,對掃描到的每一個物件判斷一下計數器是否等於0,若等於0,就會釋放該物件佔用的記憶體空間,同時將該物件引用的其他物件的計數器進行減一操作。
2.LRU演算法:LRU是Least Recently Used的縮寫,即最近最少使用,是一種常用的頁面置換演算法,選擇最近最久未使用的頁面予以淘汰。該演算法賦予每個頁面一個訪問欄位,用來記錄該頁面自上次被訪問以來所經歷的時間 t,當必須淘汰一個頁面時,選擇現有頁面中其 t 值最大的,即最近最少使用的頁面給予淘汰。LRU演算法最為經典的實現,就是HashMap+Double LinkedList,時間複雜度為O(1),但是如果按照HashMap和雙向連結串列實現,需要額外的儲存存放next和prev指標,犧牲比較大的儲存空間,顯然是不划算的。所以Redis中的LRU演算法,就是隨機取出若干個key,然後按照訪問時間排序後,淘汰掉最不經常使用的那個。
本作品採用《CC 協議》,轉載必須註明作者和本文連結