我們知道Redis支持五種數據類型,
分別是字符串、哈希表(map)、列表(list)、集合(set)和有序集合,和Java的集合框架類似,不同數據類型的數據結構實也是不一樣的。
1.Redis中的redisObject對象
Redis是使用C編寫的,內部實現了一個struct結構體redisObject對象,
通過結構體來模仿面向對象編程的“多態”,作為一個底層的數據支持,redisObject代碼:
/* * 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的底層數據結構有以下幾種:
簡單動態字符串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值:
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中的使用,就是實現有序集合數據類型。
應用版本Redis 2.6,
了解更多:Redis 數據類型