1. 程式人生 > 其它 >redis資料結構:壓縮列表

redis資料結構:壓縮列表

壓縮列表概述

壓縮列表是列表鍵和雜湊表的底層實現之一。

當一個列表鍵只包含少量列表項,並且每個列表項要麼就是小整數值, 要麼就是長度比較短的字串,那麼 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 屬性決定。

連鎖更新

插入和刪除會出現連鎖更新。