ziplist是Redis中的某些資料類型底層所使用的資料結構
Redis中的hash,List,Sorted List這幾種類型的資料在某些情況下會使用ziplist來存儲。
Hash類型
當hash類型的資料滿足以下條件時,底層使用ziplist存儲。
- 當hash鍵值對個數小于等于 hash-max-ziplist-entries 配置的值,預設512
- 當鍵值對中值的長度小于等于 hash-max-ziplist-value 配置的值,預設64
當hash類型的資料同時滿足以上兩個條件時,會将value采用ziplist來存儲。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnLiBjNxQWO2ImMiRTZ2gjYhFmM5QzM3IjM5gzNiFTMmF2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
List類型
redis中list類型的資料底層是使用quicklist來存儲的,而quicklist是基于linkedlist + ziplist實作的。
Sorted Set類型
當Sorted Set類型的資料滿足以下條件時,底層使用ziplist存儲。
- 當元素個數小于等于 zset-max-ziplist-entries配置的值,預設128
- 每個元素的值小于等于 zset-max-ziplist-value配置
當Sorted Set類型的資料同時滿足以上兩個條件時,會将value采用ziplist來存儲。
ziplist的記憶體布局
ziplist是由一系列特殊編碼的連續記憶體塊組成的順序存儲結構,類似于數組,ziplist在記憶體中是連續存儲的,但是不同于數組,為了節省記憶體 ziplist的每個元素所占的記憶體大小可以不同,每個節點可以用來存儲一個整數或者一個字元串。
ziplist類似于雙向連結清單,但是它不存儲上一個節點和下一個節點的指針,而是存儲上一個節點長度和目前節點長度,通過犧牲部分讀寫性能,來換取高效的記憶體空間使用率,節約記憶體。
- zlbytes:記錄了壓縮清單占用的記憶體位元組數,在對壓縮清單進行記憶體重配置設定,或者計算zlend的位置時使用。它本身占了4個位元組。
- zltail:記錄了尾節點(entry)至起始節點(entry)的偏移量。通過這個偏移量,可以快速确定最後一個entry節點的位址。
- zllen:記錄了entry節點的數量。當zllen的值小于65535時,這個值就表示節點的數量。當zllen的值大于65535時,節點的真實數量需要周遊整個壓縮清單才能得出。
- entry:壓縮清單中所包含的每個節點。每個節點的長度根據該節點的内容來決定。
- zlend:特殊值0XFF,标記了壓縮清單的末端。表示該壓縮清單到此為止。
值得注意的是,這個壓縮清單的記憶體空間是連續的。這也是壓縮清單的主要特點,空間連續,避免記憶體碎片,節省記憶體。
entry是連結清單中的一個節點,代表了一個資料。
redis中對壓縮清單中節點的定義如下:
typedef struct zlentry {
unsigned int prevrawlensize; /*存儲上一個節點長度的數值所需要的位元組數*/
unsigned int prevrawlen; /* 上一個節點的長度 */
unsigned int lensize; /* 目前節點長度的數值所需要的位元組數*/
unsigned int len; /* 目前節點的長度 */
unsigned int headersize; /* 目前節點的頭部大小,值 = prevrawlensize + lensize. */
unsigned char encoding; /* 編碼方式,ZIP_STR_* 或 ZIP_INT_* */
unsigned char *p; /* 指向節點内容的指針. */
} zlentry;
雖然定義了這個結構體,但是根本就沒有使用zlentry結構來作為壓縮清單中用來存儲資料節點中的結構,因為,這個結構存小整數或短字元串實在是太浪費空間了。這個結構總共在32位機占用了28個位元組(32位機),在64位機占用了32個位元組。這不符合壓縮清單的設計目的:提高記憶體的使用率。是以,在redis中,并沒有定義結構體來進行操作,而是定義了一些宏,壓縮清單的節點真正的結構如下圖所示:
- prev_entry_len:記錄前驅節點的長度。
- encoding:記錄目前節點的value成員的資料類型以及長度。
- value:根據encoding來儲存位元組數組或整數。
具體的含義,要深入了解的話,參考:ziplist源碼剖析
ziplist的特點
- 壓縮清單ziplist結構本身就是一個連續的記憶體塊,由表頭、若幹個entry節點和壓縮清單尾部辨別符zlend組成,通過一系列編碼規則,提高記憶體的使用率,使用于存儲整數和短字元串。
- 壓縮清單ziplist結構的缺點是:每次插入或删除一個元素時,都需要進行頻繁的進行記憶體的擴充或減小,然後進行資料”搬移”,甚至可能引發連鎖更新,造成嚴重效率的損失。