《Redis設計與實現》之第七章 壓縮列表

2021-09-24 17:15:25 字數 3333 閱讀 5107

壓縮列表是列表鍵和雜湊鍵的底層實現之一。壓縮列表是為了節約記憶體而開發的,是由一系列特殊編碼的連續記憶體塊組成的順序型資料結構。

【壓縮列表是一種資料結構,這種資料結構的功能是將一系列資料與其編碼資訊儲存在一塊連續的記憶體區域,這塊記憶體物理上是連續的,邏輯上被分為多個組成部分,其目的是在一定可控的時間複雜讀條件下盡可能的減少不必要的記憶體開銷,從而達到節省記憶體的效果 ————大佬總結】

一.什麼時候使用壓縮列表?

兩種情況:

當乙個列表鍵只包含少量列表項,並且每個列表項要麼是小整數值,要麼就是長度比較短的字串。

當乙個雜湊鍵只包含少量鍵值對,並且每個減值對的鍵和值要麼是小整數值,要麼就是長度表較短

二.  壓縮列表的構成

乙個壓縮列表可以包含任意多個節點(entry),每個節點可以儲存乙個位元組陣列或乙個整數值。其就是乙個位元組陣列(char *)。如圖:

除了entryx外,乙個壓縮列表其它4部分是固定的。

zlbytes:儲存乙個無符號整數,固定4個位元組長度,用來儲存壓縮列表所占用的記憶體位元組數。當對壓縮列表進行記憶體重新分配時,不需要遍歷整個列表來計算記憶體大小。

zltail:儲存乙個無符號整數,固定4個位元組長度,記錄壓縮列表尾節點距離起始位址有多少位元組(偏移量),通過這個值,程式不需要遍歷整個列表就可以確定表尾節點的位址。

zllen:壓縮列表包含的節點個數,固定兩個位元組長度,最大只能表示65535個節點,當節點數目超過65535個時,該值無效。需要遍歷列表來計算節點的個數。

entryx:列表節點,長度不定(長度由節點儲存的內容決定),由列表節點緊挨著組成。

zlend:壓縮列表結尾標誌,固定乙個位元組長度,固定值0xff(十進位制255)。

記憶體布局【壓縮列表就是一塊連續的記憶體區域】:

三,壓縮列表的節點

每個壓縮列表節點可以儲存乙個位元組陣列或乙個整數值。結構如下圖:

單位為位元組,記錄壓縮列表中前乙個節點的長度。那麼程式可以通過指正運算,根據當前節點的起始位址來計算出前乙個節點的起始位址。壓縮列表的從表尾向表頭遍歷的操作就是使用這個原理。

如果前乙個節點的長度小於254個位元組,那麼previous_entry_length長度為1個位元組,前乙個節點的長度就儲存在這乙個位元組裡

如果前乙個節點的長度大於等於254個位元組,那麼previous_entry_length長度為5個位元組,第乙個位元組設定為x0fe(十進位制254),之後的四個位元組儲存前乙個節點的長度

2. encoding

儲存了節點的content的內容型別和長度,encoding型別一共有兩種,一種是位元組陣列,一種是整數。

a,位元組陣列:

當儲存位元組陣列時,編碼長度有三種情況:

1位元組:值的最高位00,content儲存的值長度小於等於63位元組

2位元組:值的最高位01,content儲存的值長度小於等於16383位元組

5位元組:值的最高位10,content儲存的值長度小於等於4294967295位元組

b,整數:

儲存整數時,長度位乙個位元組,值的最高位用11開頭

儲存節點的值,節點的值可以是乙個位元組陣列或整數,值的型別和長度由節點的encoding屬性決定。

4. 總結:

我們發現encoding第乙個位元組的前2位元可以區分是位元組陣列(以及位元組陣列型別)還是整數;

是整數時,第3、4位元可以區分整數的型別;當content的前4個位元都是1時,後4個位元才能區分整數型別;

四,壓縮列表的原理:

相信到這裡,我們都明白了壓縮列表的原理壓縮列表並不是對資料利用某種演算法進行壓縮,而是將資料按照一定規則編碼在一塊連續的記憶體區域,目的是節省記憶體。

五,壓縮列表的應用:

1. 問題思考

redis為什麼使用壓縮列表?

使用壓縮列表的好處是什麼?

壓縮列表的應用對與我們使用記憶體有沒有什麼啟發?

2. 大佬的總結

redis對於每種資料結構、無論是列表、雜湊表還是有序集合,在決定是否應用壓縮列表作為當前資料結構型別的底層編碼的時候都會依賴乙個開關和乙個閾值,開關用來決定我們是否要啟用壓縮列表編碼,閾值總的來說通常指當前結構儲存的key數量有沒有達到乙個數值(條件),或者是value值長度有沒有達到一定的長度(條件)。任何策略都有其應用場景,不同場景應用不同策略。為什麼當前結構儲存的資料條目達到一定數值使用壓縮列表就不好?壓縮列表的新增、刪除的操作平均時間複雜度為o(n),隨著n的增大,時間必然會增加,他不像雜湊表可以以o(1)的時間複雜度找到訪問位置,然而在一定n內的時間複雜度我們可以容忍然而壓縮列表利用巧妙的編碼技術除了儲存內容盡可能的減少不必要的記憶體開銷,將資料儲存於連續的記憶體區域,這對於redis本身來說是有意義的,因為redis是一款記憶體資料庫軟體,想辦法盡可能減少記憶體的開銷是redis設計者一定要考慮的事情。

另外,經過仔細琢磨,我認為使用壓縮列表的好處除了節約記憶體之外,還有減少記憶體碎片的作用,我把這種行為叫做"合併儲存",也就是將很多小的資料塊儲存在乙個比較大的記憶體區域,試想想,如果我們將要儲存的資料都是很小的條目,我們為每乙個資料條目都單獨的申請記憶體,結果是這些條目將有可能分散在記憶體的每乙個角落,最終導致碎片增加,這是一件令人頭疼的事情。

《Redis設計與實現》之第七章 壓縮列表

壓縮列表是列表鍵和雜湊鍵的底層實現之一。壓縮列表是為了節約記憶體而開發的,是由一系列特殊編碼的連續記憶體塊組成的順序型資料結構。壓縮列表是一種資料結構,這種資料結構的功能是將一系列資料與其編碼資訊儲存在一塊連續的記憶體區域,這塊記憶體物理上是連續的,邏輯上被分為多個組成部分,其目的是在一定可控的時間...

Linux核心設計與實現 第七章

一些簡單基礎的概念就不過多介紹了,著重說一些比較新的和重要的東西 我們對中斷處理程式有兩個要求 一是執行速度快,而是完成的任務量多。鑑於兩者此消彼長的關係,我們將中斷處理分為兩部分 上半部 接受乙個中斷,就立即執行,但只做有嚴格時限的工作,例如對中斷進行應答或復位硬體,這些工作都是在所有中斷被禁止的...

第七章 巨集與列舉

規則7 1 1 用巨集定義表示式時,要使用完備的括號。說明 m為巨集只是簡單的 替換,不會像函式一樣先將引數計算後,再傳遞。示例 如下定義的巨集都存在一定的風險。反例 若有除法運算,c a b計算錯誤 define rectangle area a,b a b a 1 b 1計算錯誤 define ...