redis資料結構:壓縮列表
阿新 • • 發佈:2021-07-18
壓縮列表概述
壓縮列表是列表鍵和雜湊表的底層實現之一。
當一個列表鍵只包含少量列表項,並且每個列表項要麼就是小整數值, 要麼就是長度比較短的字串,那麼 Redis 就會使用壓縮列表來做列表鍵的底層實現。
另外, 當一個雜湊鍵只包含少量鍵值對, 並且每個鍵值對的鍵和值要麼就是小整數值, 要麼就是長度比較短的字串, 那麼 Redis 就會使用壓縮列表來做雜湊鍵的底層實現。
壓縮列表的組成
壓縮列表是 Redis 為了節約記憶體而開發的, 由一系列特殊編碼的連續記憶體塊組成的順序型(sequential)資料結構。
一個壓縮列表可以包含任意多個節點(entry), 每個節點可以儲存一個位元組陣列或者一個整數值
屬性 | 型別 | 長度 | 用途 |
---|---|---|---|
zlbyte | uint32_t | 4位元組 | 記錄整個壓縮列表佔用的記憶體位元組數:在對壓縮列表進行記憶體重分配, 或者計算 zlend 的位置時使用。 |
zltail | uint32_t | 4位元組 | 記錄壓縮列表表尾節點距離壓縮列表的起始地址有多少位元組: 通過這個偏移量,程式無須遍歷整個壓縮列表就可以確定表尾節點的地址。 |
zllen | uint16_t | 2 位元組 | 記錄了壓縮列表包含的節點數量: 當這個屬性的值小於 UINT16_MAX (65535)時, 這個屬性的值就是壓縮列表包含節點的數量; 當這個值等於 UINT16_MAX 時, 節點的真實數量需要遍歷整個壓縮列表才能計算得出。 |
entryX | 列表節點 | 不定 | 壓縮列表包含的各個節點,節點的長度由節點儲存的內容決定。 |
zlend | uint8_t | 1 位元組 | 特殊值 0xFF (十進位制 255 ),用於標記壓縮列表的末端。 |
壓縮列表節點的構成
每個壓縮列表節點可以儲存一個位元組陣列或者一個整數值,其中
位元組陣列可以是以下三種長度的其中一種:
- 長度小於等於 63 (2^{6}-1)位元組的位元組陣列;
- 長度小於等於 16383 (2^{14}-1) 位元組的位元組陣列;
- 長度小於等於 4294967295 (2^{32}-1)位元組的位元組陣列;
整數值則可以是以下六種長度
- 4 位長,介於 0 至 12 之間的無符號整數;
- 1 位元組長的有符號整數;
- 3 位元組長的有符號整數;
- int16_t 型別整數;
- int32_t 型別整數;
- int64_t 型別整數。
每個壓縮列表節點都由 previous_entry_length 、 encoding 、 content 三個部分組成
previous_entry_length
所以程式可以通過指標運算, 根據當前節點的起始地址來計算出前一個節點的起始地址。
previous_entry_length:以位元組為單位, 記錄了壓縮列表中前一個節點的長度。
previous_entry_length:屬性的長度可以是 1 位元組或者 5 位元組:
- 如果前一節點的長度小於 254 位元組, 那麼 previous_entry_length 屬性的長度為 1 位元組: 前一節點的長度就儲存在這一個位元組裡面。
- 如果前一節點的長度大於等於 254 位元組, 那麼 previous_entry_length 屬性的長度為 5 位元組: 其中屬性的第一位元組會被設定為 0xFE (十進位制值 254), 而之後的四個位元組則用於儲存前一節點的長度。
encoding
encoding 屬性記錄了節點的 content 屬性所儲存資料的型別以及長度:
- 一位元組、兩位元組或者五位元組長, 值的最高位為 00 、 01 或者 10 的是位元組陣列編碼: 這種編碼表示節點的 content 屬性儲存著位元組陣列, 陣列的長度由編碼除去最高兩位之後的其他位記錄;
- 一位元組長, 值的最高位以 11 開頭的是整數編碼: 這種編碼表示節點的 content 屬性儲存著整數值, 整數值的型別和長度由編碼除去最高兩位之後的其他位記錄;
位元組陣列編碼
編碼 | 編碼長度 | content 屬性儲存的值 |
---|---|---|
00bbbbbb | 1 位元組 | 長度小於等於 63 位元組的位元組陣列。 |
01bbbbbb xxxxxxxx | 2 位元組 | 長度小於等於 16383 位元組的位元組陣列。 |
10______ aaaaaaaa bbbbbbbb cccccccc dddddddd | 5 位元組 | 長度小於等於 4294967295 的位元組陣列。 |
整數編碼
編碼 | 編碼長度 | content 屬性儲存的值 |
---|---|---|
11000000 | 1 位元組 | int16_t 型別的整數。 |
11010000 | 1 位元組 | int32_t 型別的整數。 |
11100000 | 1 位元組 | int64_t 型別的整數。 |
11110000 | 1 位元組 | 24 位有符號整數。 |
11111110 | 1 位元組 | 8 位有符號整數。 |
1111xxxx | 1 位元組 | 使用這一編碼的節點沒有相應的 content 屬性, 因為編碼本身的 xxxx 四個位已經儲存了一個介於 0 和 12 之間的值, 所以它無須 content 屬性。 |
content
節點的 content 屬性負責儲存節點的值, 節點值可以是一個位元組陣列或者整數, 值的型別和長度由節點的 encoding 屬性決定。
連鎖更新
插入和刪除會出現連鎖更新。