目錄
1 五種基本數據對象
2 數據結構對象分析
Redis中的每個對象都由一個redisObject結構表示,該結構中保存數據相關的三個屬性分別是:type、encoding、ptr。
redis.h
typedef struct redisObject {
//類型
unsigned type:4;
unsigned notused:2;
//編碼
unsigned encoding:4;
unsigned lru:22;
//引用計數
int refcount;
//指向底層實現數據結構的指針
void *ptr;
} robj;
2.1 類型
對象的type屬性記錄了對象的類型,這個屬性的值可以是表2-1列出對的常量中的一個。
對象 | 對象type屬性的值 | TYPE命令的輸出 |
字符串對象 | REDIS_STRING | string |
列表對象 | REDIS_LIST | list |
哈希對象 | REDIS_HASH | hash |
集合對象 | REDIS_SET | set |
有序集合對象 | REDIS_ZSET | zset |
TYPE命令的實現方式也與此類似,當我們對一個數據庫鍵執行TYPE命令時,命令返回的結果爲數據庫鍵對應的值對象類型,而不是鍵對象類型:
# 鍵爲字符串對象,值爲字符串對象
127.0.0.1:6379> SET msg "hello world"
OK
127.0.0.1:6379> TYPE msg
string
# 鍵爲字符串對象,值爲列表對象
127.0.0.1:6379> RPUSH numbers 1 3 5
(integer) 3
127.0.0.1:6379> TYPE numbers
list
# 鍵爲字符串對象,值爲哈希對象
127.0.0.1:6379> HMSET profile name Tome age 25 career Programmer
OK
127.0.0.1:6379> TYPE profile
hash
# 鍵爲字符串對象,值爲集合對象
127.0.0.1:6379> SADD fruits apple banana cherry
(integer) 3
127.0.0.1:6379> TYPE fruits
set
# 鍵爲字符串對象,值爲有序集合對象
127.0.0.1:6379> ZADD price 8.5 apple 5.0 banana 6.0 cherry
(integer) 3
127.0.0.1:6379> TYPE price
zset
2.2 編碼與底層實現
對象的ptr指針指向對象的底層實現數據結構,而這些數據結構由對象的encoding屬性決定。encoding屬性記錄了對象使用的編碼,也即是說這個對象使用了什麼數據結構作爲對象的底層實現,這個屬性的值可以是表2-2列出的常量的其中一個。
對象所使用的底層數據結構 | 編碼常量 | OBJECT ENCODING命令輸出 |
整數 | REDIS_ENCODING_INT | int |
embstr編碼的簡單動態字符串(SDS) | REDIS_ENCODING_EMBSTR | embstr |
簡單動態字符串 | REDIS_ENCODING_RAW | raw |
字典 | REDIS_ENCODING_HT | hashtable |
雙端鏈表 | REDIS_ENCODING_LINKEDLIST | linkedlist |
壓縮列表 | REDIS_ENCODING_ZIPLIST | ziplist |
整數集合 | REDIS_ENCODING_INTSET | intset |
跳躍表和字典 | REDIS_ENCODING_SKIPLIST | skiplist |
使用OBJECT ENCODING命令可以查看一個數據庫鍵的值對象的編碼:
127.0.0.1:6379> SET msg "hello wrold"
OK
127.0.0.1:6379> OBJECT ENCODING msg
"embstr"
127.0.0.1:6379> SADD numbers 1 3 5
(integer) 3
127.0.0.1:6379> OBJECT ENCODING numbers
"intset"
127.0.0.1:6379> SADD numbers "seven"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING numbers
"hashtable"
每種類型的對象都至少使用了兩種不同的編碼,表2-3列出了每種類型的對象可以使用的編碼:
類型 | 編碼 | 對象 |
REDIS_STRING | REDIS_ENCODING_INT | 使用整數值實現的字符串對象 |
REDIS_STRING | REDIS_ENCODING_EMBSTR | 使用embstr編碼的簡單動態字符串實現的字符串對象 |
REDIS_STRING | REDIS_ENCODING_RAW | 使用簡單動態字符串實現的字符串對象 |
REDIS_LIST | REDIS_ENCODING_ZIPLIST | 使用壓縮列表實現的列表對象 |
REDIS_LIST | REDIS_ENCODING_LINKEDLIST | 使用雙端鏈表實現的列表對象 |
REDIS_HASH | REDIS_ENCODING_ZIPLIST | 使用壓縮列表實現的哈希對象 |
REDIS_HASH | REDIS_ENCODING_HT | 使用字典實現的哈希對象 |
REDIS_SET | REDIS_ENCODING_INTSET | 使用整數集合實現的集合對象 |
REDIS_SET | REDIS_ENCODING_HT | 使用字典實現的集合對象 |
REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 使用壓縮列表實現的有序集合對象 |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 使用跳躍表和字典實現的有序集合對象 |
2.3 編碼轉換
(1)字符串對象
- 對於int編碼的字符串對象來說,如果我們向對象執行了一些命令,使得對象保存的不再是整數值,而是一個字符串值,那麼字符串對象將從int變爲raw。
- 對embstr編碼的字符串對象執行任何修改命令時,程序先將對象的編碼從embstr轉換成raw,然後再執行修改命令。
(2)列表對象
當列表對象可以同時滿足以下兩個條件時,列表對象使用ziplist編碼:
- 列表對象保存的所有字符串元素的長度都小於64字節
- 列表對象保存的元素數量小於512個
(3)哈希對象
當哈希對象可以同時滿足以下兩個條件時,哈希對象使用ziplist編碼:
- 哈希對象保存的所有鍵值對的鍵和值的字符串長度都小於64字節
- 哈希對象保存的鍵值對數量小於512個
(4)集合對象
當集合對象可以同時滿足以下兩個條件時,對象使用intset編碼:
- 集合對象保存的所有元素都是整數值
- 集合對象保存的元素數量不超過512個
(5)有序集合
當有序集合對象可以同時滿足以下條件時,對象使用ziplist編碼:
- 有序集合保存的元素數量小於128個
- 有序集合保存的所有元素的長度小於64字節
參考:
1、redis設計與實現(第二版)