redis是一種nosql數據庫,redis操作數據庫都是通過相關命令來進行的。而且由於redis內存實現很多底層的數據結構,數據庫存儲的值也是這些數據結構。redis 每個命令都是對應相應的數據結構實現的。例如:LPUSH 和LLEN 只能用於列表鍵,而SADD 和SRANDMEMBER 只能用於集合鍵。從上面可以看出來,Redis 必須讓每個鍵都帶有類型信息,使得程序可以檢查鍵的類型,併爲它選擇合適的處理方式。
另外redis的實現的數據結構都有自己的編碼,這就說明,每當操作某種數據結構的時候就根據不同的編碼方式採用不同的操作。這種種都說明對數據庫的操作需要根據數據結構的不同,編碼方式的不同進行不同的處理。這樣做豈不是很複雜?
redis爲了解決這種問題,自定義了一種數據結構-------對象。下面來看下對象結構:
typedef struct redisObject {
// 類型
unsigned type:4;
// 不使用(對齊位)
unsigned notused:2;
// 編碼方式
unsigned encoding:4;
// LRU 時間(相對於 server.lruclock)
unsigned lru:22;
// 引用計數
int refcount;
// 指向對象的值
void *ptr;
} robj;
type類型包括以下幾種:
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4
encoding也包括以下幾種:
#define REDIS_ENCODING_RAW 0 /* Raw representation */
#define REDIS_ENCODING_INT 1 /* Encoded as integer */
#define REDIS_ENCODING_HT 2 /* Encoded as hash table */
#define REDIS_ENCODING_ZIPMAP 3 /* Encoded as zipmap */
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_INTSET 6 /* Encoded as intset */
#define REDIS_ENCODING_SKIPLIST 7 /* Encoded as skiplist */
ptr就是指向要存儲的數據結構。refcount就是引用這個對象的計數器。
注:type並不能指明這是哪種數據結構,數據結構的類型需要通過type和encoding一起才能確定。
下面用張圖來講述數據結構類型,type,encoding三者之間的關係:
從上圖可以看出不同數據結構類型對應的type以及編碼方式。對象這個數據結構的出現就是爲了實現redis操作數據庫的便利。所有對redis數據庫的操作都會把底層的數據結構封裝成redisObject後輸入到redis數據庫中。