簡介
從資料型別上體現就是,同一個資料型別,在不同的情況下會使用不同的編碼型別,底層所使用的的資料結構也不相同。
字串物件
字串物件的編碼可以是 int
、raw
和 embstr
三者之一。
embstr
編碼是專門用於儲存簡短字串的一種最佳化編碼方式,與 raw
編碼會呼叫兩次記憶體分配函式分別建立 redisObject
結構和 sdshdr
結構不同,embstr
只會使用一次記憶體分配函式建立一塊連續的記憶體空間同時存放 redisObject
結構和 sdshdr
結構。
字串轉換編碼的條件如下:
- 如果字串物件儲存的是整數值並且不超過
long
的範圍時,優先選擇使用int
作為編碼方式 - 如果儲存的字串長度大於 32 個位元組,會使用
raw
編碼的簡單動態字串作為儲存 - 如果儲存的字串長度小於 32 個位元組,會使用
embstr
編碼的簡單動態字串作為儲存
字串物件中有兩個需要注意的地方:
- 對於儲存浮點數的字串物件,實際上這個浮點數是以字串值來儲存的,執行如
INCRBYFLOAT
這樣的命令時,Redis 會先將字串轉換成浮點數計算,然後再轉換成字串值儲存 int
編碼和embstr
編碼在條件滿足下會轉換成raw
編碼。embstr
在執行修改命令之後總是會轉換成raw
編碼,這個過程是不可逆的
列表物件
在 3.2 版本之前,列表物件的編碼可以是 ziplist
或者 zlinkedlist
的其中一個;在 3.2 版本之後,列表物件的編碼只能是 quicklist
。
雜湊物件
雜湊物件的編碼可以是 ziplist
或者 hashtable
中的一個。
雜湊物件使用 ziplist
作為底層實現的時候,每當有新的鍵值對要插入雜湊物件時,Redis 會先儲存鍵的壓縮列表節點到壓縮列表的表尾,然後再儲存值的壓縮列表節點到壓縮列表的表尾。
當雜湊物件同時滿足以下兩個條件時,雜湊物件使用 ziplist
編碼:
- 雜湊物件儲存的所有鍵值對的鍵和值的字串長度都小於 64 位元組
- 雜湊物件儲存的鍵值對數量小於 512 個
集合物件
集合物件的編碼可以是 intset
或者 hashtable
中的一個。
hashtable
編碼的集合物件使用字典作為底層實現,字典的每個鍵都是字串物件,這個字串物件包含著集合元素,字典的每個值都直接儲存 NULL
。
當集合物件同時滿足以下兩個條件時,集合物件使用 intset
編碼:
- 集合物件儲存的所有元素都是整數值
- 集合物件儲存的元素資料不超過 512 個
有序集合物件
有序集合物件的編碼可以是 ziplist
或者 skiplist
中的一個。
有序集合物件使用 ziplist
編碼作為底層實現時,每個集合物件會使用兩個緊挨在一起的壓縮列表節點來儲存,第一個節點儲存元素的成員,第二個元素則儲存元素的分值。
這裡有一點需要注意,skiplist
編碼的有序集合使用 zset
結構作為底層實現,一個 zset
結構包含一個字典和一個跳錶。其中字典的鍵儲存元素的成員,字典的值儲存元素的分值;跳錶的 object
屬性儲存元素的成員,跳錶的 score
屬性儲存元素的分值。
理論上有序集合可以只使用字典或者跳錶實現,但是使用兩個結構冗餘儲存有序集合物件的成員和分值,既保留了字典 \(O(1)\) 時間複雜度查詢的效率,也保留了跳錶範圍型操作的所有優點。
當同時滿足以下兩個條件時,有序集合會使用 ziplist
編碼:
- 有序集合儲存的元素數量小於 128 個
- 有序集合儲存的所有元素成員的長度都小於 64 位元組