標籤:
雖然內部資料結構非常強大,但是建立一系列完整的資料結構本身也是一件相當耗費記憶體的工作,當一個對象包含的元素數量並不多,或者元素本身的體積並不大時,使用代價高昂的內部資料結構並不是最好的辦法。
為瞭解決這一問題,Redis在條件允許的情況下,會使用記憶體映射資料結構來代替內部資料結構。
記憶體映射資料結構可以為使用者節省大量的記憶體。不過,因為記憶體映射資料結構的編碼和操作方式要比內部資料結構要複雜得多,所以記憶體映射資料結構所佔用的CPU 時間會比作用類似的內部資料結構要多。
這一部分將對Redis目前正在使用的兩種記憶體映射資料結構進行介紹。
整數集合
整數集合(intset)用於有序、無重複地儲存多個整數值,它會根據元素的值,自動選擇該用什麼長度的整數類型來儲存元素。
Intset是集合鍵的底層實現之一,如果一個集合:
1. 只儲存著整數元素;
2. 元素的數量不多;
那麼Redis就會使用intset來儲存集合元素。
根據需要,intset可以自動從int16_t 升級到int32_t 或int64_t ,或者從int32_t 升級到int64_t 。
typedefstructintset {
// 儲存元素所使用的類型的長度
uint32_tencoding;
// 元素個數
uint32_tlength;
// 儲存元素的數組
int8_tcontents[];
} intset;
執行個體
現在,我們要要將一個長度為int32_t 的值65535 加入到集合中,intset需要執行以下步驟:
1. 將encoding 屬性設定為INTSET_ENC_INT32 。
2. 根據encoding 屬性的值,對contents 數組進行記憶體重分配。
3. 因為原來的3 個int16_t 值還“擠在”contents 前面的48 個位裡,所以程式需要對它們進行移動和類型轉換,從而讓它們適應集合的新編碼方式。
4. 最後,將新值65535 添加到數組:
•Intset用於有序、無重複地儲存多個整數值,它會根據元素的值,自動選擇該用什麼長度的整數類型來儲存元素。
•當一個位長度更長的整數值添加到intset時,需要對intset進行升級,新intset中每個元素的位長度都等於新添加值的位長度,但原有元素的值不變。
•升級會引起整個intset進行記憶體重分配,並移動集合中的所有元素,這個操作的複雜度為O(N) 。
•Intset只支援升級,不支援降級。
•Intset是有序的,程式使用二分尋找演算法來實現尋找操作,複雜度為O(lgN) 。
壓縮列表
Ziplist是由一系列特殊編碼的記憶體塊構成的列表,一個ziplist可以包含多個節點(entry),每個節點可以儲存一個長度受限的字元數組(不以\0 結尾的char 數組)或者整數。
•字元數組
–長度小於等於63 (26 ??1)位元組的字元數組
–長度小於等於16383 (214 ??1)位元組的字元數組
–長度小於等於4294967295 (232 ??1)位元組的字元數組
•整數
–4 位長,介於0 至12 之間的不帶正負號的整數
–1 位元組長,有符號整數
–3 位元組長,有符號整數
–int16_t 類型整數
–int32_t 類型整數
–int64_t 類型整數
ziplist是由一系列特殊編碼的記憶體塊構成的列表,它可以儲存字元數組或整數值,它還是雜湊鍵、列表鍵和有序集合鍵的底層實現之一。
redisbook筆記——redis記憶體映射資料結構