1. 程式人生 > >Redis5.0原始碼解析(六)----------Redis物件

Redis5.0原始碼解析(六)----------Redis物件

基於Redis5.0

之前介紹了 Redis 用到的所有主要資料結構, 比如簡單動態字串(SDS)、雙端連結串列、字典、跳躍表、整數集合, 等等,但Redis 並沒有直接使用這些資料結構來實現鍵值對資料庫, 而是基於這些資料結構建立了一個物件系統, 這個系統包含字串物件、列表物件、雜湊物件、集合物件和有序集合物件這五種型別的物件, 每種物件都用到了至少一種我們前面所介紹的資料結構

物件的型別與編碼

Redis 使用物件來表示資料庫中的鍵和值, 每次當我們在 Redis 的資料庫中新建立一個鍵值對時, 我們至少會建立兩個物件, 一個物件用作鍵值對的鍵(鍵物件), 另一個物件用作鍵值對的值(值物件)

Redis 中的每個物件都由一個 redisObject 結構表示, 該結構中和儲存資料有關的三個屬性分別是 type 屬性、 encoding 屬性和 ptr 屬性:

//server.h

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
int refcount; // 指向底層實現資料結構的指標 void *ptr; } robj;
  • type:儲存物件使用的資料型別,命令type {key}返回值物件的資料型別
  • encoding:儲存物件使用的內部編碼型別,命令object encoding {key}返回值物件的內部編碼型別
  • lru:記錄物件最後一次被訪問的時間(用於記憶體回收),命令object idletime {key}檢視鍵的空閒時間,LRU/LFU
  • refcount:記錄物件的引用計數(用於回收),命令object refcount {key}檢視鍵的引用數
  • ptr
    :指向底層實現資料結構的指標

型別

物件的 type 屬性記錄了物件的型別

//server.h

/*-----------------------------------------------------------------------------
 * Data types
 *----------------------------------------------------------------------------*/

/* A redis object, that is a type able to hold a string / list / set */

/* The actual Redis Object */
#define OBJ_STRING 0    /* String object. */
#define OBJ_LIST 1      /* List object. */
#define OBJ_SET 2       /* Set object. */
#define OBJ_ZSET 3      /* Sorted set object. */
#define OBJ_HASH 4      /* Hash object. */

/* The "module" object type is a special one that signals that the object
 * is one directly managed by a Redis module. In this case the value points
 * to a moduleValue struct, which contains the object value (which is only
 * handled by the module itself) and the RedisModuleType struct which lists
 * function pointers in order to serialize, deserialize, AOF-rewrite and
 * free the object.
 *
 * Inside the RDB file, module types are encoded as OBJ_MODULE followed
 * by a 64 bit module type ID, which has a 54 bits module-specific signature
 * in order to dispatch the loading to the right module, plus a 10 bits
 * encoding version. */
#define OBJ_MODULE 5    /* Module object. */
#define OBJ_STREAM 6    /* Stream object. */

對於 Redis 資料庫儲存的鍵值對來說, 鍵總是一個字串物件, 而值則可以是字串物件、列表物件、雜湊物件、集合物件或者有序集合物件的其中一種

# 鍵為字串物件,值為字串物件

redis> SET msg "hello world"
OK

redis> TYPE msg
string

# 鍵為字串物件,值為列表物件

redis> RPUSH numbers 1 3 5
(integer) 6

redis> TYPE numbers
list

# 鍵為字串物件,值為雜湊物件

redis> HMSET profile name Tome age 25 career Programmer
OK

redis> TYPE profile
hash

# 鍵為字串物件,值為集合物件

redis> SADD fruits apple banana cherry
(integer) 3

redis> TYPE fruits
set

# 鍵為字串物件,值為有序集合物件

redis> ZADD price 8.5 apple 5.0 banana 6.0 cherry
(integer) 3

redis> TYPE price
zset

編碼

物件的 ptr 指標指向物件的底層實現資料結構, 而這些資料結構由物件的 encoding 屬性決定,encoding 屬性記錄了物件所使用的編碼, 也即是說這個物件使用了什麼資料結構作為物件的底層實現

//server.h

/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 * is set to one of this fields for this object. */
#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */

通過 encoding 屬性來設定物件所使用的編碼, 而不是為特定型別的物件關聯一種固定的編碼, 極大地提升了 Redis 的靈活性和效率, 因為 Redis 可以根據不同的使用場景來為一個物件設定不同的編碼, 從而優化物件在某一場景下的效率

redis> SET msg "hello wrold"
OK

redis> OBJECT ENCODING msg
"embstr"

redis> SET story "long long long long long long ago ..."
OK

redis> OBJECT ENCODING story
"raw"

redis> SADD numbers 1 3 5
(integer) 3

redis> OBJECT ENCODING numbers
"intset"

redis> SADD numbers "seven"
(integer) 1

redis> OBJECT ENCODING numbers
"hashtable"

接下來我們將分別介紹 Redis 中的五種不同型別的物件, 說明這些物件底層所使用的編碼方式

  • 字串物件
  • 列表物件
  • 雜湊物件
  • 集合物件
  • 有序集合物件