redis 壓縮列表

2021-10-01 02:30:48 字數 2831 閱讀 6273

壓縮列表是列表鍵雜湊鍵的底層實現之一。當乙個列表鍵只包含少量列表項,並且每個列表項要麼就是小整數值,要麼就是長度比較短的字串,那麼redis就會使用壓縮列表來做列表鍵的底層實現。 另外,當乙個雜湊鍵只包含少量鍵值對,並且每個鍵值對的鍵和值要麼就是小整數值,要麼就是長度比較短的字串,那麼redis就會使用壓縮列表來做雜湊鍵的底層實現,例如:

# 後續更新將某些情況改造成了quicklist快速列表

127.0.0.1:6379> rpush lst 1 3 5 10086 "hello"

"world"

(integer) 6

127.0.0.1:6379> object encoding lst

"quicklist"

# zip;ist壓縮列表

127.0.0.1:6379> hmset profile "name"

"jack"

"age" 28 "job"

"programmer"

ok127.0.0.1:6379> object encoding profile

"ziplist"

壓縮列表是由一些列特殊編碼的連續記憶體塊組成的順序型資料結構,乙個壓縮列表可包含任意多個節點(entry),每個節點可以儲存乙個位元組陣列或者乙個整數值。下面兩個圖分別展示了壓縮列表的組成部分和各部分的型別、長度及用途:

每個壓縮列表節點可以儲存乙個位元組陣列或者乙個整數值,其中位元組陣列可以是以下三種長度之一:

而整數值可以是以下六種長度之一:

每個壓縮列表節點都由previous_entry_length、encoding、content三個部分組成,如下圖所示,我們分別介紹、

2.1 previous_entry_length

節點的previous_entry_length屬性以位元組為單位,記錄了壓縮列表中前乙個節點的長度。previous_entry_length屬性的長度可以是1位元組或者5位元組:

因為節點的previous_entry_length屬性記錄了前乙個節點的長度,所以程式可以通過指標運算,根據當前節點的起始位址來計算出前乙個節點的起始位址。而壓縮列表的從表尾向表頭遍歷操作就是使用這一原理實現的,只要我們擁有了乙個指向某個節點起始位址的指標,那麼通過這個指標以及這個節點的previous_entry_length屬性,程式就可以一直向前乙個節點回溯,最終到達壓縮列表的表頭節點。例如下面這個例子:

節點的encoding屬性記錄了節點的content屬性所儲存資料的型別長度

兩張表分別記錄了乙個節點儲存位元組陣列和整數值的情況,其中下劃線表示留空不儲存資訊。

編碼編碼長度

content屬性儲存的值

00bbbbbb

1位元組長度小於等於63(26-1)位元組的位元組陣列

01bbbbbb ******xx

2位元組長度小於等於16383(214-1)位元組的位元組陣列

00_ _ _ _ _ _ aaaaaaaaa bbbbbbbb cccccccc dddddddd

5位元組長度小於等於(232-1)位元組的位元組陣列 編碼

編碼長度

content屬性儲存的值

11000000

1位元組int16_t型別的整數

11010000

1位元組int32_t型別的整數

11100000

1位元組int64_t型別的整數

11110000

1位元組24位有符號整數

11111110

1位元組8位有符號整數

1111***x

1位元組使用此編碼表示沒有相應的content屬性,因為編碼本身的後四位***已經儲存了乙個0~12的值

2.3 content

節點的content屬性負責儲存節點的值,節點值可以是乙個位元組陣列或者整數,值的型別和長度由節點的encoding屬性決定。例如下面的例子,其中:

前面說過,每個節點的previous_entry_length屬性都記錄著前乙個節點的長度,且前一節點長度是否大於254位元組決定了本節點此屬性佔位情況。而這個屬性previous_entry_length也是導致連鎖更新的原因。

現在假設這種情況:乙個壓縮列表中所有節點e1至en的長度都小於254位元組,那麼previous_entry_length的屬性均占用1位元組。這時我們將乙個長度大於等於254位元組的新節點new設定為壓縮列表的表頭節點,那麼因為new後面節點e1的previous_entry_length屬性僅為1位元組,沒辦法儲存新節點new的長度,所以需要將壓縮列表的空間重新分配,並將e1節點的previous_entry_length屬性從原來的1位元組擴充套件為5位元組。而由於它擴充套件了以後e1的長度大於254,導致e2也進行同樣的操作,依次類推後面所有節點都要進行此操作。

同樣進行刪除節點也可能出現與此相反的一系列操作,即不斷壓縮每個節點的previous_entry_length從5位元組變為1位元組。最壞情況下可能會對壓縮列表進行n次空間重分配,而每次空間重分配的最壞時間複雜度也為o(n),所以連鎖更新的最壞複雜度為o(n2)。

當然出現這種情況的概率是較低的,我們也不用過多的擔心。

Redis之壓縮列表

壓縮列表 ziplist 是列表鍵和雜湊鍵的底層實現之一。當乙個列表鍵只包含少量列表項,並且每個列表項要麼就是小整數值,要麼就是長度比較短的字串,redis就會使用壓縮列表來做列表鍵的底層實現。下面看一下壓縮列表實現的列表鍵 列表鍵裡面包含的都是1 3 5 10086這樣的小整數值,以及 hello...

redis筆記 壓縮列表

1.壓縮列表 壓縮列表是列表鍵和雜湊鍵的底層實現之一,當包含的少量列表項並且列表項是小整數值或者較短字串時,redis會使用壓縮列表鍵的底層實現 2.壓縮列表的構成 zlbytes 壓縮列表的總長 zltail 尾節點距離壓縮列表起始位址的便宜量 zllen 表示壓縮列表包含的節點數量 3.壓縮列表...

Redis中的壓縮列表

壓縮列表 ziplist 是列表鍵和雜湊鍵的底層實現之一。當乙個列表鍵只包含少量列表項,並且每個列表項要麼就是小整數值,要麼就是長度比較短的字串,那麼redis就會使用壓縮列表來做列表鍵的底層實現。例如,執行以下命令將建立乙個壓縮列表實現的列表鍵 127.0 0.1 6379 rpush 1st 1...