我們知道Redis支持五種數據類型, 分別是字元串、哈希表(map)、列表(list)、集合(set)和有序集合,和Java的集合框架類似,不同數據類型的數據結構實也是不一樣的。 1.Redis中的redisObject對象 Redis是使用C編寫的,內部實現了一個struct結構體redisObj ...
我們知道Redis支持五種數據類型,
分別是字元串、哈希表(map)、列表(list)、集合(set)和有序集合,和Java的集合框架類似,不同數據類型的數據結構實也是不一樣的。
1.Redis中的redisObject對象
Redis是使用C編寫的,內部實現了一個struct結構體redisObject對象,
通過結構體來模仿面向對象編程的“多態”,作為一個底層的數據支持,redisObject代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/*
* 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、encoding、ptr3個屬性分別表示:
type:redisObject的類型,字元串、列表、集合、有序集、哈希表
encoding:底層實現結構,字元串、整數、跳躍表、壓縮列表等
ptr:實際指向保存值的數據結構
如果一個 redisObject 的 type 屬性為 REDIS_LIST , encoding 屬性為 REDIS_ENCODING_LINKEDLIST ,
那麼這個對象就是一個 Redis 列表,它的值保存在一個雙端鏈表內,而 ptr 指針就指向這個雙端鏈表;
如果一個 redisObject 的 type 屬性為 REDIS_HASH , encoding 屬性為 REDIS_ENCODING_ZIPMAP ,
那麼這個對象就是一個 Redis 哈希表,它的值保存在一個 zipmap 里,而 ptr 指針就指向這個 zipmap 。
下麵這張圖片中的REDIS_STRING/REDIS_LIST/REDIS_ZSET/REDIS_HASH/REDIS_SET針對的是redisObject中的type,
後面指向的REDIS_ENCODING_LINKEDLIST等針對的是encoding欄位。
Redis的底層數據結構有以下幾種:
Redis的底層數據結構有以下幾種:
簡單動態字元串sds(Simple Dynamic String)
雙端鏈表(LinkedList)
字典(Map)
跳躍表(SkipList)
下麵針對五種數據類型,學習相關的底層數據結構。
2.String
如果一個String類型的value能夠保存為整數,則將對應redisObject 對象的encoding修改為REDIS_ENCODING_INT,將對應robj對象的ptr值改為對應的數值。
如果不能轉為整數,保持原有encoding為REDIS_ENCODING_RAW。
因此String類型的數據可能使用原始的字元串存儲(實際為sds - Simple Dynamic Strings,對應encoding為REDIS_ENCODING_RAW)或者整數存儲。
Redis可以直接查看對象的ENCODING值:
1 2 3 4 5 6 7 8 |
redis:6379> set strtest 1
OK
redis:6379> OBJECT ENCODING strtest
"int"
redis:6379> set strtest blog
OK
redis:6379> OBJECT ENCODING strtest
"raw"
|
3.List
列表的底層實現有2種:
REDIS_ENCODING_ZIPLIST
REDIS_ENCODING_LINKEDLIST
ZIPLIST相比LINKEDLIST可以節省記憶體,
當創建新的列表時,預設是使用壓縮列表作為底層數據結構的。
Redis內部會對相關操作做判斷,
當list的elem數小於配置值: hash-max-ziplist-entries 或者elem_value字元串的長度小於 hash-max-ziplist-value, 可以編碼成 REDIS_ENCODING_ZIPLIST 類型存儲,以節約記憶體;
但由於在zip list添加和刪除元素會涉及到數據移動,
因此當list內容較多時,使用雙向鏈表。
4.Hash
創建新的Hash類型時,預設也使用ziplist存儲value,保存數據過多時,使用hast table。
5.Set
集合的底層實現也有兩種:
REDIS_ENCODING_INTSET
REDIS_ENCODING_HT(字典)
創建Set類型的key-value時,如果value能夠表示為整數,則使用intset類型保存value。
數據量大時,切換為使用hash table保存各個value。
6.Sorted Set
有序集合的底層實現也是2種:
REDIS_ENCODING_ZIPLIST
REDIS_ENCODING_SKIPLIST
關於Redis中的跳躍表,查看這篇文章:跳躍表
跳躍表在 Redis中的使用,就是實現有序集合數據類型。