Redis壓縮列表的詳細介紹(示例講解)

本篇文章給大家帶來的內容是關于redis壓縮列表的詳細介紹(示例講解),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

此篇文章是主要介紹Redis在數據存儲方面的其中一種方式,壓縮列表。

本文會介紹

1、壓縮列表(ziplist)的使用場景?

2.如何達到節約內存的效果?

3.壓縮列表的存儲格式?

4. 連鎖更新的問題??

5. conf文件配置。

在實踐上的操作主要是對conf配置文件進行配置,具體上沒有確切的一個值,更多是經驗值。也有的項目會直接使用原本的默認值。此篇對于更好地理解一個數據庫底層的存儲邏輯會有一點幫助。修學儲能,既要博,也要淵。希望這篇文章對同樣也是在學習Redis的各位同伴有點用。(推薦教程:Redis教程

一、壓縮列表(ziplist)的使用場景:

Redis為了優化數據存儲,節約內存,在列表、字典(哈希鍵)和有序集合的底層實現了使用壓縮列表這一優化方案。

例如,假如一個哈希鍵里面存儲的字符串比較短,那么Redis就會將它用壓縮列表的格式去存儲,即轉換為字節數組存儲。而一個哈希鍵內部存儲的整數值比較小,同樣也會把它存儲為壓縮列表的一個節點。同理,列表鍵的對小數據的存儲跟哈希鍵的操作類似。

如此說來,壓縮列表并不是開發者可以直接調用的Redis中的一種存儲數據結構,而是Redis中為優化數據存儲而在底層做的一項努力。理解好這點還是比較重要的。

二、如何達到節約內存的效果?

壓縮列表是一種序列化的數據結構,這種數據結構的功能是將一系列數據與其編碼信息存儲在一塊連續的內存區域,這塊內存物理上是連續的。但邏輯上被分為多個組成部分,即節點。目的是為了在一定可控的時間復雜度條件下盡可能的減少不必要的內存開銷,從而達到節省內存的效果。需要理解是怎么達到節約內存作用的,還需要去了解壓縮列表的存儲格式。

三、壓縮列表的存儲格式:

壓縮列表(ziplist)是Redis列表鍵、哈希鍵和有序集合鍵的底層實現之一,其實質是一種序列化的數據存儲結構。有別于普通情況下,Redis用雙端鏈表表示列表,使用散列表表示哈希鍵,用散列表+跳躍表表示有序集合。當一個列表或者哈希字典/有序集合只包含很少內容,并且每一個列表項或者哈希項/有序集合項如果是小整數,或者比較短的字符串。那么Redis就會用壓縮列表來做底層的實現。

壓縮列表由一系列經Redis特殊編碼的連續內存塊組成,每一個內存塊稱為一個節點(entry),而一個壓縮列表可以包含很多個節點。每個節點存儲的數據格式可以是字節數組(中文字符串等都會轉換為字節數組)或者整數值。

字節數組的長度可以是以下的其中一種:

1. 長度小于等于63字節(2的6次方)

2. 長度小于等于16383字節(2的14次方)

3. 長度小于等于4294967295字節(2的32次方)

整數值可能是以下六種中的其中一種:

1. 4位長,介于0-12之間的無符號整數

2. 1字節長的有符號整數

3. 3字節長的有符號整數

4. int16_t類型整數

5. int32_類型整數

6. int64_t類型整數

普通存儲格式下和壓縮列表存儲格式下的不同點:

列表存儲結構典型的為雙端鏈表,每一個值都是用一個節點來表示,每個節點都會有指向前一個節點和后一個節點的指針,以及指向節點包含的字符串值的指針。而字符串值又分為3個部分存儲,第一部分存儲字符串長度,第二部分存儲字符串值中剩余可用的字節量,第三部分存儲的則是字符串數據本身。所以一個節點往往都需要存儲3個指針、2個記錄字符串信息的整數、字符串本省和一個額外的字節。總體上額外的開銷是很大的(21字節)。

壓縮列表節點的格式:

Redis壓縮列表的詳細介紹(示例講解)

每一個節點都有previous_entry_length,encoding,content三個部分組成,在遍歷壓縮列表的時候是從后往前遍歷的。

1. previous_entry_length記錄了前一個節點的長度,只要用當前指針減去這個值就可以達到前一個節點的起始地址。

2. encoding記錄了節點content屬性所保存數據的類型和長度

Redis壓縮列表的詳細介紹(示例講解)

3. content記錄了一個節點的值

顯然壓縮列表這種方式節約了不少存儲空間。但同時也會引發下面的問題。

四、連鎖更新的問題:

一般而言如果前一個節點的整體長度小于254字節,previous_entry_length屬性只需要1個字節的空間來保存這個長度值。而當前一個節點大于254字節的時候,previous_entry_length屬性要用5個字節長的空間來記錄長度值。

當長度為254字節左右的節點前插入一個新的節點的時候,需要增加previous_entry_length來記錄這個節點到新節點的偏移量。這個時候,這個節點的長度肯定就大于254字節了。所以這個節點的后一個節點就不能只用一個字節的previous_entry_length來記錄這個節點的信息了,而是需要5個字節來記錄。如果連續多個節點的長度都為254字節左右,在其中的某一個節點前/后發生節點的插入和刪除(刪除的推理與插入相反,原本用5字節記錄前一節點的可能變為1字節),都可能引發連鎖的更新,顯然,這樣對系統地運行效率是很不利的。不過,在實際應用中這種情況還是比較少發生的。

而雙端鏈表在節點的更新、增加和刪除上顯得就會“輕松”很多了。 因為每一個節點存儲的信息都是相對獨立的。??

實踐意義:

要預估一個節點大概占據多少字節的存儲空間,適當地調整字段的存儲格式而不要使存儲的字段值占據存儲空間落在254字節(除去encoding屬性和previous_entry_length屬性)左右。

Redis中查看字符串和哈希鍵值的長度相關命令:

1. 查詢字符串鍵對應的值長度

命令:

strlen

例如:

127.0.0.1:6379> strlen m_name

(Integer) 8

2. 查詢哈希鍵某一個域長度

命令:

Hstrlen

例如:

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

五、Conf文件配置:

通過修改配置文件,可以控制是否使用壓縮列表存儲相關鍵的最大元素個數和最大元素的大小

Conf文件中的配置:
1.

[] -max-ziplist-entries : 表示對于鍵的最大元素個數,即一個鍵中在該指定值下的數量的節點個數都會用壓縮列表來儲存

[] -max-ziplist-value :表示壓縮列表中每個節點的最大體積是多少字節

實際使用中,一個列表鍵/哈希鍵的某一個元素往往存儲著比較大的信息量,會大于64字節,所以配置時很有可能會比64大,同時考慮到實際存儲數據的容量大小以及上面談到的previous_entry_length的大小問題,對[] -max-ziplist-value進行合理的配置。

配置文件內容:

##############?ADVANCED?CONFIG?########################## 哈希鍵 #?Hashes?are?encoded?using?a?memory?efficient?data?structure?when?they?have?a #?small?number?of?entries,?and?the?biggest?entry?does?not?exceed?a?given #?threshold.?These?thresholds?can?be?configured?using?the?following?directives. hash-max-ziplist-entries?512 hash-max-ziplist-value?64  有序集合鍵 #?Similarly?to?hashes?and?lists,?sorted?sets?are?also?specially?encoded?in #?order?to?save?a?lot?of?space.?This?encoding?is?only?used?when?the?length?and #?elements?of?a?sorted?set?are?below?the?following?limits: zset-max-ziplist-entries?128 zset-max-ziplist-value?64  列表鍵,比較特殊,直接使用制定大小kb字節數表示(有些conf文件的列表鍵與hash鍵的表達式沒太大區別) #?Lists?are?also?encoded?in?a?special?way?to?save?a?lot?of?space. #?The?number?of?entries?allowed?per?internal?list?node?can?be?specified #?as?a?fixed?maximum?size?or?a?maximum?number?of?elements. #?For?a?fixed?maximum?size,?use?-5?through?-1,?meaning: #?-5:?max?size:?64?Kb??<p>案例:</p><p>修改配置前使用默認配置:</p><p>hash-max-ziplist-entries 512</p><p>hash-max-ziplist-value 64</p><p>127.0.0.1:6379&gt; hstrlen good_list good_list1</p><p>(integer) 226</p><p>127.0.0.1:6379&gt; Object encoding good_list</p><p>"hashtable"</p><p>修改配置:</p><p>hash-max-ziplist-entries 512</p><p><strong>hash-max-ziplist-value 254</strong></p><p>注意:修改配置后需要重啟服務器</p><p>127.0.0.1:6379&gt; hstrlen good_list good_list1</p><p>(integer) 226</p><p>127.0.0.1:6379&gt; object encoding good_list</p><p><strong>"ziplist"</strong></p><p>可以看到存儲方式已將變為ziplist</p><p><strong>較官方的壓力測試和指導建議:</strong></p><p>當一個壓縮列表的元素數量上升到幾千(實際使用可能遠小于這個值)的時候,壓縮列表的性能可能會下降,因為Redis在操作這種結構的時候,編解碼會出現一定的壓力。</p><p>壓縮列表的長度限制在500-2000之內,每個元素體積限制在128字節或以下,壓縮列表的的性能都會處于合理范圍之內。</p><p>		</p>

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享