redis-壓縮列表
壓縮列表是列表鍵和哈希鍵的底層實現之一。當列表和哈希表滿足一定條件的時候,底層將採用壓縮列表實現,具體將在之後介紹redis對象的時候詳細講解。
壓縮列表的定義
壓縮列表是Redis爲了節約內存的使用而開發的。壓縮列表使用一塊經過特殊編碼的連續內存。壓縮列表包括多個節點,每個節點可以是一個字節數組或一個整數值。
圖1
圖1是壓縮列表的組成部分,各個字段解釋如下:
屬性 | 類型 | 長度 | 用途 |
---|---|---|---|
zlbytes | uint32_t | 4字節 | 記錄整個壓縮列表佔有的字節數 |
zltail | uint32_t | 4字節 | 記錄壓縮列表表尾節點距離壓縮列表起始地址有多少個字節 |
zllen | uint16_t | 2字節 | 記錄了壓縮列表包含的節點數量:當這個屬性值小於65535時,這個值就是包含的節點數量,否則需要遍歷列表才能計算包含的節點數量 |
entryX | 列表節點 | 不定 | 壓縮列表包含的節點,節點的長度由節點保存的內容決定 |
zlend | uint8_t | 1字節 | 特殊值0xFF(10進制255),用於標記壓縮列表的末端 |
壓縮列表節點的定義
壓縮列表節點可以保存一個字節數組或者一個整數。壓縮列表節點的組成部分如圖2示。
圖2
previous_entry_length表示的是前一個節點長度,以字節爲單位。previous_entry_length屬性的長度可以是1字節或者5字節。
- 如果前一節點的長度小於254字節,那麼previous_entry_length的長度爲1字節,前一節點的長度就保存在這1個字節裏。例如對於圖3,指示前一節點的長度爲8字節。
圖3
- 如果前一節點的長度大於等於254字節,那麼previous_entry_length的長度爲5字節,其中第一個字節爲0xFE,後四個字節用於保存前一個節點的長度。例如對於圖4,指示前一節點的長度爲257(0X0101)字節。
圖4
因爲previous_entry_length記錄了前一節點的長度,所以程序可以根據當前節點的指針計算出前一節點的指針,從而可以從尾部向頭部遍歷。
encoding屬性記錄了節點content屬性所保存數據的類型和長度。
- 值的最高位分別爲00、01、10,長度分別是1字節、2字節、5字節,這種編碼方式表示content屬性記錄的是字節數組,字節數組的長度爲encoding去除最高2位後的其他位記錄(5字節的只有後4個字節用來記錄長度)。如下表示:(注:-表示空的,a、b、c、d、x代表實際有效的2進制數字)
編碼 編碼長度 content保存的值 00bbbbbb 1字節 長度小於等於63的字節數組 01bbbbbb xxxxxxxx 2字節 長度小於等於2^14^-1的字節數組 10—— aaaaaaaa bbbbbbbb cccccccc dddddddd 5字節 長度小於等於2^32^-1的字節數組 - 值的最高位爲11開頭的是整數編碼,整數的類型由編碼除去最高二位的其他位記錄。如下表示:
編碼 編碼長度 content保存的值 11000000 1字節 int16_t類型的整數 11010000 1字節 int32_t類型的整數 11100000 1字節 int64_t類型的整數 11110000 1字節 24位有符號整數 11111110 1字節 8位有符號整數 1111xxxx 1字節 這一編碼方式沒有content屬性,xxxx本身就記錄了0-15的值 content屬性記錄實際的節點值,有了encoding編碼方式,content屬性就很好理解了。舉兩個例子,圖5示一個長度爲11的字節數組節點。其中編碼方式爲00001011。
圖5
圖6示一個類型爲int16_t類型的整數。其中編碼方式爲11000000。
圖6
連鎖更新
對於圖1,假設節點entry1到entryN的長度都介於250-253字節長度之間,那麼所有節點的previous_entry_length的長度都是1個字節。若此時在entry1之前插入一個長度大於等於254字節的節點,因爲entry1的previous_entry_length長度只有一個字節,因此程序需要對壓縮列表空間進行再分配,並將entry1的previous_entry_length長度從原來的1字節擴展爲5字節。
entry1擴展後增加了4個字節,它的長度介於254-257,而entry2的previous_entry_length無法保存該長度的值,這將再一次觸發再分配動作。更進一步,將引發雪崩般的效應。此所謂連鎖更新。因爲每次內存重分配的時間複雜度爲O(N),所以連鎖更新的時間複雜度爲O(N^2^)。
幸運的是,這種情況實際上並不常見,我們可以放心的使用。
參考:
- Redis設計與實現. 黃健宏著